控制分割精度

Controlling division precision

考虑以下简单的除法:

A=8.868;
A/0.1
ans =
  88.679999999999993

由于浮点精度,这会导致一个小错误。有什么办法可以防止这种情况发生吗?基本上我所做的就是将逗号移动一个位置,同时不接近 MATLAB 中允许的最大位数。

我想获得如下结果:

A/0.1
ans =
  88.68

尾随零无关紧要,只要它们只是零,并且不包含第 14 位左右的数字。

有趣的是,当四舍五入到 N 位时也会出现此问题:

R = (randi([8659 49847],[1e3 1]))/1e3;
xmin = min(R);
el = 0.1;
step = 1/el;
tmp1=xmin/el;
tmp2=round(tmp1);
tmp3=round(tmp2*el,3);

tmp3 =
   8.699999999999999

使用符号数学,您可以获得精确的结果:

x=sym('8.868')/sym('.1')

您可以随时使用 fixed point arithmetics where the slope is a multiple of 10. You won't have any inaccuracies when you multiply/divide by ten. In Matlab, you can use Fixed Point Toolbox

编辑: 根据您的评论 - 看起来您可以将斜率设置为 0.05。

您可以将数字表示为整数的分数。只要不转为浮点数,就不会丢失精度:

A = 8.868;
div = 0.1;
[N1,D1] = rat(A);
[N2,D2] = rat(div);
% divide A by div:
N = N1 * D2;
D = N2 * D1;

当然,您的数字一开始可能并不精确,如其他 answers/comments 中所述。分数转换也可以引入近似值,但这取决于你处理的数字和 rat.

tol 参数

发布此答案只是为了我的案例的完整性。


我使用 unique 的第三个输出在我的案例中稍微规避了这个问题:

el = 0.25;
A = (randi([7364 84635],[1e4 1]))/1e3;
B = A/el;
C = round(B);
D = C*el;
[tmp1,tmp2,tmp3] = unique(D);
E = tmp1(tmp3,:);
all(E==D)
ans = 
     1

哪个正确地进行了装箱。因此,即使中心点可能不精确到无限精度,它们至少在 10 位数字以内,这超过了我原始数据的 3 位数字精度。