gpt4 book ai didi

floating-point - 当 `expr` 嵌套在 Tcl 中时,为什么算术结果不同?

转载 作者:行者123 更新时间:2023-12-05 00:00:36 25 4
gpt4 key购买 nike

知道由于浮点数的内部表示而导致的不准确性(请参阅 Wikipedia ,搜索到:“相等性测试的使用”...),在执行以下操作时仍然有惊喜:

% expr int(0.57 * 10000)
5699
% expr int([expr 0.57 * 10000])
5700

嵌套 expr禁止?为什么它会改变传递的浮点值?或者它是否改变了执行浮点运算的顺序,那些影响结果的顺序?

更新:关于 comparing floating point numbers with speed 主题的好书(和辅助链接), some basics and not so basics here ,并在 the IEEE 754-2008 standard's description .

最佳答案

这是一个有趣的问题,因为它涉及一些微妙的事情。

% expr int(0.57 * 10000)
5699

这段代码(没有替换,所以它“不出所料”地工作)表明浮点数本身就是令人惊讶的东西。特别是,0.57 没有精确表示为 IEEE double 浮点数(以 2 为基数);事实上,它的表示比刚好 0.57 低一点,所以当四舍五入时(这就是 int(...) 所做的;10000 本身是精确的)你会下降到 5699。你也会看到其他语言的相同行为.
% expr int([expr 0.57 * 10000])
5700

现在这特别有趣。您首先看到的是内部计算正在完成,结果浮点数转换为字符串(因为真的没有其他方法可以做到)。现在, 您必须使用 Tcl 8.4 (或之前)默认数字呈现规则(实际上)是通过打印数字的前 15 位有效数字而得到的;在这种情况下,给你 5700.00000000000 (好吧,右边有一些零的截断)然后从头开始重新解释为第一个 double (正好​​是 5700.0),然后转换为 5700。

数字转换规则在 Tcl 8.5 中发生了变化。如今,当 Tcl 将浮点数转换为字符串时,它会生成最短的字符串,该字符串将转换回完全相同的浮点数(即,通过字符串领域的一次旅行将在结果 double 中给出相同的位模式)。这反过来意味着您现在永远不会看到上述两件事之间的区别。 (如果您真的想强制使用固定数量的小数位,请使用 format %.15g [expr 0.57 * 10000] 。)

如果你正确地支撑你的表达,你也不会在 8.0 到 8.4 中观察到的行为,因为十多年来社区一直建议人们这样做:
$ tclsh8.4
% expr {int([expr 0.57 * 10000])}
5699

那是因为这不会强制内部 expr 的结果调用被解释为字符串。 (它也更快更安全。)

关于floating-point - 当 `expr` 嵌套在 Tcl 中时,为什么算术结果不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9903803/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com