![]() |
为什么在MATLAB中24.0000不等于24.0000?
我正在编写一个程序,需要删除存储在矩阵中的重复点。问题在于,当检查这些点是否在矩阵中时,MATLAB无法识别它们是否存在(尽管它们存在)。
在以下代码中, intersections函数获取相交点: [points(:,1), points(:,2)] = intersections(... obj.modifiedVGVertices(1,:), obj.modifiedVGVertices(2,:), ... [vertex1(1) vertex2(1)], [vertex1(2) vertex2(2)]); 结果: >> points points = 12.0000 15.0000 33.0000 24.0000 33.0000 24.0000 >> vertex1 vertex1 = 12 15 >> vertex2 vertex2 = 33 24 应从结果中消除两个点( vertex1和vertex2 )。应该通过以下命令完成: points = points((points(:,1) ~= vertex1(1)) | (points(:,2) ~= vertex1(2)), :); points = points((points(:,1) ~= vertex2(1)) | (points(:,2) ~= vertex2(2)), :); 完成此操作后,我们得到以下意外结果: >> points points = 33.0000 24.0000 结果应该是一个空矩阵。如您所见,第一对(或第二对[33.0000 24.0000]已被消除,但第二对则没有。 然后我检查了这两个表达式: >> points(1) ~= vertex2(1) ans = 0 >> points(2) ~= vertex2(2) ans = 1 % > points points = Empty matrix: 0-by-2 回答: 您遇到的问题与如何在计算机上表示[URL="https://www.mathworks.com/help/matlab/matlab_prog/floating-point-numbers.html"]浮点数[/URL]有关。在我的答案(“浮点表示”部分)的末尾出现了有关浮点表示的更详细的讨论。 [B]TL; DR[/B]版本:由于计算机的内存量有限,因此数字只能以有限的精度表示。因此,浮点数的精度被限制为一定的小数位数( [URL="https://en.wikipedia.org/wiki/Double-precision_floating-point_format"]双精度值[/URL]大约为16个有效数字,这是MATLAB中的默认[URL="https://en.wikipedia.org/wiki/Double-precision_floating-point_format"]值[/URL] )。 [B]实际与显示精度[/B] 现在来解决问题中的特定示例... [B]虽然以相同的方式[I]显示[/I] 24.0000和24.0000 ,但事实证明,在这种情况下,它们实际上相差很小的十进制数。您不会看到它,因为MATLAB [URL="https://www.mathworks.com/help/matlab/ref/format.html"]默认情况下仅显示4个有效数字[/URL] ,从而使整体显示保持整洁。[/B]如果要查看全精度,则应发出format long命令或查看数字的[URL="https://www.mathworks.com/help/matlab/ref/num2hex.html"]十六进制表示形式[/URL] : >> pi ans = 3.1416 >> format long >> pi ans = 3.141592653589793 >> num2hex(pi) ans = 400921fb54442d18 [B]初始化值与计算值[/B] 由于只能为浮点数表示有限数量的值,因此计算可能导致值介于这两种表示之间。在这种情况下,结果必须四舍五入到其中之一。这引入了一个小的[URL="https://en.wikipedia.org/wiki/Machine_epsilon"]机器精度误差[/URL] 。这也意味着直接初始化值或通过某种计算初始化值可能会产生稍微不同的结果。例如,值0.1没有[I]精确的[/I]浮点表示(即,它略微四舍五入),由于舍入误差的累积方式,您最终会得到类似直觉的结果: >> a=sum([0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]); % Sum 10 0.1s >> b=1; % Initialize to 1 >> a == b ans = logical 0 % They are unequal! >> num2hex(a) % Let's check their hex representation to confirm ans = 3fefffffffffffff >> num2hex(b) ans = 3ff0000000000000 [B]如何正确处理浮点比较[/B] 由于浮点值可能相差很小,因此任何比较都应通过检查这些值是否在彼此的某个范围内(即公差),而不是彼此完全相等来进行。例如: a = 24; b = 24.000001; tolerance = 0.001; if abs(ab) < tolerance, disp('Equal!'); end 将显示“等于!”。 然后,您可以将代码更改为: points = points((abs(points(:,1)-vertex1(1)) > tolerance) | ... (abs(points(:,2)-vertex1(2)) > tolerance),:) [B]浮点表示[/B] 浮点数(特别是[URL="https://en.wikipedia.org/wiki/IEEE_floating_point"]针对浮点算术[/URL]的[URL="https://en.wikipedia.org/wiki/IEEE_floating_point"]IEEE 754标准[/URL] )是浮点数的一个很好的概述, [URL="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html"][I]这是每位计算机科学家都应该[/I][/URL]对David Goldberg所掌握的浮点[URL="https://en.wikipedia.org/wiki/IEEE_floating_point"]算术[/URL]有所[URL="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html"][I]了解[/I][/URL] 。 二进制浮点数实际上由三个整数表示:符号位s ,有效位(或系数/分数) b和指数e 。 [URL="https://en.wikipedia.org/wiki/Double-precision_floating-point_format"]对于双精度浮点格式[/URL] ,每个数字由在内存中布置的64位表示,如下所示: [URL="https://i.stack.imgur.com/KTTPX.png"][IMG]https://i.stack.imgur.com/KTTPX.png[/IMG][/URL] 然后,可以通过以下公式找到实际值: [URL="https://i.stack.imgur.com/nV0ly.png"][IMG]https://i.stack.imgur.com/nV0ly.png[/IMG][/URL] 此格式允许在10 ^ -308到10 ^ 308范围内的数字表示。对于MATLAB,您可以从[URL="https://www.mathworks.com/help/matlab/ref/realmin.html"]realmin[/URL]和[URL="https://www.mathworks.com/help/matlab/ref/realmax.html"]realmax[/URL]获得这些限制: >> realmin ans = 2.225073858507201e-308 >> realmax ans = 1.797693134862316e+308 由于用于表示浮点数的位数有限,因此在上述给定范围内只能表示这么多的有限数。计算通常会得出与这些有限表示形式之一不完全匹配的值,因此必须对这些值进行四舍五入。如上面的示例中所讨论的,这些[URL="https://en.wikipedia.org/wiki/Machine_epsilon"]机器精度错误[/URL]以不同的方式使其明显。 为了更好地理解这些舍入误差,查看函数[URL="https://www.mathworks.com/help/matlab/ref/eps.html"]eps[/URL]提供的相对浮点精度是有用的,该函数量化了从给定数到下一个最大浮点表示的距离: >> eps(1) ans = 2.220446049250313e-16 >> eps(1000) ans = 1.136868377216160e-13 注意,精度是[I]相[/I]对于表示的给定数字的大小而言的。较大的数字将在浮点表示形式之间具有更大的距离,因此在小数点后的精度位数将减少。在进行一些计算时,这可能是一个重要的考虑因素。考虑以下示例: >> format long % Display full precision >> x = rand(1, 10); % Get 10 random values between 0 and 1 >> a = mean(x) % Take the mean a = 0.587307428244141 >> b = mean(x+10000)-10000 % Take the mean at a different scale, then shift back b = 0.587307428244458 请注意,当我们将x的值从[0 1]范围移动到[10000 10001]范围时,计算平均值,然后减去平均值偏移量进行比较,我们得到的值对于最后3个有效数字是不同的。这说明了数据的偏移量或缩放比例如何改变对其执行的计算的准确性,这是某些问题必须解决的问题。 [url=https://stackoverflow.com/questions/686439]更多&回答...[/url] |
所有时间均为北京时间。现在的时间是 23:35。 |
Powered by vBulletin
版权所有 ©2000 - 2025,Jelsoft Enterprises Ltd.