GNU/Octave中如何不受数值精度影响比较有理数?
解决Octave浮点精度导致算术等式判断失效的全局方案
Hey,我完全懂你用Octave教孩子算术时遇到的这个糟心问题——明明数学上绝对成立的等式,Octave却返回0,还要用繁琐的转换才能得到正确结果,太破坏教学的流畅性了!
先再明确下你遇到的问题:
>> 2/3 + 1/6 == 5/6 ans = 0
为啥会这样?
这锅得甩给浮点数的二进制存储特性:像2/3这种分数没法用二进制浮点数精确表示,计算后会残留一个极其微小的误差。你可以直接算差值验证:
>> 2/3 + 1/6 - 5/6 ans = -1.11022302462516e-16
就是这个几乎可以忽略的非零值,让Octave判定两个数不相等。
现有方法的问题
用rat做有理化或者转成single类型确实能解决,但这些操作把简洁的算术表达式搞得复杂不堪,对教孩子来说完全没必要:
>> all(rat(2/3 + 1/6) == rat(5/6)) ans = 1 >> single(2/3 + 1/6) == single(5/6) ans = 1
全局解决方案:设置比较容差
好在Octave有个专门的全局变量comparison_tolerance,能帮你搞定这个问题!它的作用是指定一个误差范围,只要两个数的差小于这个范围,就会被判定为相等。
具体操作
只需要把这个变量设为一个合适的容差值就行,比如用Octave默认的机器精度eps:
>> comparison_tolerance = eps; >> 2/3 + 1/6 == 5/6 ans = 1
如果是教孩子,你甚至可以设一个更宽松的容差(比如1e-15),完全不影响算术教学的准确性:
>> comparison_tolerance = 1e-15; >> 2/3 + 1/6 == 5/6 ans = 1
恢复严格判断
之后如果需要回到默认的严格相等判断,把容差设回0就好:
>> comparison_tolerance = 0; >> 2/3 + 1/6 == 5/6 ans = 0
这样设置后,你就能用最简洁的算术表达式教孩子,再也不用被浮点精度问题打断教学节奏啦!
内容的提问来源于stack exchange,提问作者nightcod3r
相关产品推荐
相关产品推荐

