将复制值与原始值进行比较时是否存在精度问题?
Are there precision issues when comparing a copied value with the original value?
考虑以下工作流程:
A = [2/3 exp(1) 5];
match = interp1(A, A, 2, 'next');
第二个命令查找A的值,它在2之后的第一个。因此,match
等于exp(1)
。
我有两个问题:
- 我可以期望
A == match
的计算结果总是 [0 1 0]
吗?
- 如果
B = [exp(1) exp(1) exp(1)]
,B == match
的结果是什么?
如果 exp(1)
被其他无理数或超越数代替,答案会改变吗?
在内存中复制一个值时,任何存在的浮点错误都将按原样复制,因为毕竟复制操作只是将位复制到内存中的新位置,然后实际上没有执行任何算术运算,也不会引入新的精度误差。
因此,浮点数(有精度错误)与该数字的精确副本之间的比较将始终相等。
也就是说,您的示例假定 interp1
中的下一个邻居插值的实现只是复制数据。虽然这在当前版本中可能是正确的,但肯定会发生变化。如果将来 interp1
被重写以代替执行一些浮点运算来进行下一个邻居插值,那么您的比较将意外失败。因此,即使在这种情况下,我也不鼓励使用 ==
进行比较。
浮点错误的差异(对于相同的计算)通常是由不同的 types 和 order 引起的操作。对于 exp(1)
的示例,人们会期望内置的 exp
函数会执行相同的操作顺序,因此,对于相同的(相同的)输入,输出值都将具有相同的精度误差。因此,您的比较将产生 [1 1 1]
.
同样,这对内置函数的内部构成了一个假设,最终可能会反噬你。同样对于这种比较,我会避免使用 ==
只是为了确保您的代码按预期运行,而不管 MATLAB 的函数内部实现如何。
更新
我可能不会像您所示那样进行比较来尝试确定下一个邻居的位置,而只是执行以下操作以获得相同的结果。
ind = find(A > 2);
或者如果你真的需要一个逻辑数组。
[0 diff(A > 2) == 1]
或者,您始终可以在 A
中找到最接近匹配项的值,方法如下:
[~, ind] = min(abs(A - match))
更新 2
对于您在评论中提供的示例
C = [exp(1) exp(1) exp(1) 1 1 pi*4 pi*4 pi*4 pi*4];
C == mode(C);
您正在做出(合理的)假设,即 mode
return 是被发现为众数的值的精确副本。尽管在上面的比较中,问题是您 also 假设输入数组中出现的所有 pi*4
都是 also 完全相等。所以基本上,如果 mode
return 是一个精确副本,比较 C == mode(C)
将 return 在 至少 1 匹配但可以 return 多达 4 个匹配项,具体取决于 "equal" 所有 4*pi
条目的匹配程度。
考虑以下工作流程:
A = [2/3 exp(1) 5];
match = interp1(A, A, 2, 'next');
第二个命令查找A的值,它在2之后的第一个。因此,match
等于exp(1)
。
我有两个问题:
- 我可以期望
A == match
的计算结果总是[0 1 0]
吗? - 如果
B = [exp(1) exp(1) exp(1)]
,B == match
的结果是什么?
如果 exp(1)
被其他无理数或超越数代替,答案会改变吗?
在内存中复制一个值时,任何存在的浮点错误都将按原样复制,因为毕竟复制操作只是将位复制到内存中的新位置,然后实际上没有执行任何算术运算,也不会引入新的精度误差。 因此,浮点数(有精度错误)与该数字的精确副本之间的比较将始终相等。
也就是说,您的示例假定
interp1
中的下一个邻居插值的实现只是复制数据。虽然这在当前版本中可能是正确的,但肯定会发生变化。如果将来interp1
被重写以代替执行一些浮点运算来进行下一个邻居插值,那么您的比较将意外失败。因此,即使在这种情况下,我也不鼓励使用==
进行比较。浮点错误的差异(对于相同的计算)通常是由不同的 types 和 order 引起的操作。对于
exp(1)
的示例,人们会期望内置的exp
函数会执行相同的操作顺序,因此,对于相同的(相同的)输入,输出值都将具有相同的精度误差。因此,您的比较将产生[1 1 1]
.同样,这对内置函数的内部构成了一个假设,最终可能会反噬你。同样对于这种比较,我会避免使用
==
只是为了确保您的代码按预期运行,而不管 MATLAB 的函数内部实现如何。
更新
我可能不会像您所示那样进行比较来尝试确定下一个邻居的位置,而只是执行以下操作以获得相同的结果。
ind = find(A > 2);
或者如果你真的需要一个逻辑数组。
[0 diff(A > 2) == 1]
或者,您始终可以在 A
中找到最接近匹配项的值,方法如下:
[~, ind] = min(abs(A - match))
更新 2
对于您在评论中提供的示例
C = [exp(1) exp(1) exp(1) 1 1 pi*4 pi*4 pi*4 pi*4];
C == mode(C);
您正在做出(合理的)假设,即 mode
return 是被发现为众数的值的精确副本。尽管在上面的比较中,问题是您 also 假设输入数组中出现的所有 pi*4
都是 also 完全相等。所以基本上,如果 mode
return 是一个精确副本,比较 C == mode(C)
将 return 在 至少 1 匹配但可以 return 多达 4 个匹配项,具体取决于 "equal" 所有 4*pi
条目的匹配程度。