在我的应用程序中,我正在计算经过的时间(a-b),我得到了
0.4999978542327881
(由python打印),我想如果它没有被python四舍五入打印的话,它真的是0.4999978542327880859375
。
我确实相信
a-b
应该是0.5
如果我用笔和纸来做的话。我的猜测是,由于 0.4999978542327880859375
、a
和结果值的浮点数表示形式的限制,我得到 b
。
我对这个错误很满意,并且我考虑了公差。
我的问题确实是:有没有一个程序可以得到
a
和b
?我的意思是我想得到两个十进制数a
和b
,当使用笔和纸相减时给出0.5
和然后使用浮点运算(IEEE 754)会给我0.4999978542327880859375
。我可以打印 a
和 b
但我无法真正重现错误,因为它取决于经过的时间。
例如,假设我有
(a-b) = 0.19999999999999998
,并且我知道如果我使用 简单的“人类”算术而不是浮点算术,它应该是
0.2
。我想将 a
和 b
的值逆向工程为 0.3
和 0.1
因为我知道常规算术中的 0.3-0.1==0.2
但浮点算术中的 0.3-0.1==0.19999999999999998
因为 0.1
最接近的表示是0.1000000000000000055511151231257827021181583404541015625
。
该过程不需要为
a
和 b
生成唯一值。所有可能的 (a,b)
对的列表会更有用,这样我就可以搜索最合适的示例,因为我知道发生这种情况的大致时间,并且 a
和 b
是自纪元以来的时间戳(以秒为单位):漂浮。例如,在这个特定的实例中,我知道 a
和 b
都必须在 1704964314.0
('2024-01-11T09:11:54.000+00:00') 和 1704964316.0
('2024-01) 之间-11T09:11:56.000+00:00')
我对
0.4999978542327881
的特殊情况感兴趣,但也对获取特定结果示例的一般程序感兴趣。为什么?因为我想提供我在应用程序日志中找到的每个浮点“错误”的输入值示例(针对 github 问题)。
第一步是使用非十进制表示法进行分析:
下面打印
0x1.ffff7p-2 0x1.ffff7p-2
,暗示问题可能仅限于float
值,而不是double
。
int main() {
double d = 0.4999978542327880859375;
printf("%a\n%a\n", d, (float) d);
return 0;
}
添加以下代码,我们看到
0x1.ffff7p-2
距离 0.5 为 72 float
。这个简单数学减法的距离意味着 a - b
距离是由于值 about 大于 0.5 72 倍而产生的。 (在这里挥手数学。)
unsigned count = 0;
while (d < 0.5) {
d = nextafterf(d, 0.5);
count++;
}
printf("%X\n", count);
除此之外,我们正在进入更多 ifs,并且确实需要更多信息才能进行更多工作。