int((0.1+0.7)*10) = 7 在多种语言中。如何防止这种情况发生?

发布于 2024-11-16 18:26:18 字数 1167 浏览 2 评论 0原文

最近我遇到了多种语言的错误/功能。我对它是如何引起的有非常基本的了解(并且我想要一些详细的解释),但是当我想到这些年来我必须犯的所有错误时,问题是我如何确定“嘿,这可能会导致一个可笑的错误,我最好使用任意精度函数”,其他哪些语言确实有这个错误(以及那些没有的语言,为什么 >)。另外,为什么 0.1+0.7 会这样做,而 0.1+0.3 不会,还有其他众所周知的例子吗?

PHP

//the first one actually doesn't make any sense to me,
//why 7 after typecast if it's represented internally as 8?
debug_zval_dump((0.1+0.7)*10); //double(8) refcount(1)
debug_zval_dump((int)((0.1+0.7)*10)); //long(7) refcount(1)
debug_zval_dump((float)((0.1+0.7)*10)); //double(8) refcount(1)

Python:

>>> ((0.1+0.7)*10)
7.9999999999999991
>>> int((0.1+0.7)*10)
7

Javascript:

alert((0.1+0.7)*10); //7.999999999999999
alert(parseInt((0.7+0.1)*10)); //7

Ruby:

>> ((0.1+0.7)*10).to_i                                                  
=> 7                                                                    
>>((0.1+0.7)*10)                                                       
=> 7.999999999999999                                                    

Recently I came across a bug/feature in several languages. I have a very basic knowledge about how it's caused (and I'd like some detailed explanation), but when I think of all the bugs I must have made over the years, the question is how can I determine "Hey, this might cause a riddiculous bug, I'd better use arbitrary precision functions", what other languages do have this bug (and those who don't, why). Also, why 0.1+0.7 does this and i.e. 0.1+0.3 doesn't, are there any other well-known examples?

PHP

//the first one actually doesn't make any sense to me,
//why 7 after typecast if it's represented internally as 8?
debug_zval_dump((0.1+0.7)*10); //double(8) refcount(1)
debug_zval_dump((int)((0.1+0.7)*10)); //long(7) refcount(1)
debug_zval_dump((float)((0.1+0.7)*10)); //double(8) refcount(1)

Python:

>>> ((0.1+0.7)*10)
7.9999999999999991
>>> int((0.1+0.7)*10)
7

Javascript:

alert((0.1+0.7)*10); //7.999999999999999
alert(parseInt((0.7+0.1)*10)); //7

Ruby:

>> ((0.1+0.7)*10).to_i                                                  
=> 7                                                                    
>>((0.1+0.7)*10)                                                       
=> 7.999999999999999                                                    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

神妖 2024-11-23 18:26:19

这不是语言问题。这是浮点运算的普遍问题。

It's not a language issue. It's general issue with float point arithmetic.

三岁铭 2024-11-23 18:26:19

停止使用浮动。不,真的。

Stop using floats. No, really.

一念一轮回 2024-11-23 18:26:19

数字的浮点表示并不精确

在 Python 中,int 将浮点数向零截断为最接近的整数。
PHP 中的 (int)、Javascript 中的 parseInt 和 Ruby 中的 to_i 执行相同的操作。

这不是一个错误;而是一个错误。这就是这些函数的工作原理。

例如,来自 Python 的 int文档

浮点数的转换
到整数截断(向零)。

The floating point representation of numbers is not exact.

In Python, int truncates floats towards zero to the nearest integer.
(int) in PHP, parseInt in Javascript, and to_i in Ruby do the same thing.

This is not a bug; it's just how these functions work.

For example, from the docs for Python's int:

Conversion of floating point numbers
to integers truncates (towards zero).

喵星人汪星人 2024-11-23 18:26:19

这是一个与浮点表示有关的已知问题,您可以在此处找到更多信息:

http://en.wikipedia.org/wiki/IEEE_754-2008

具体问题是,7.9在转换为int的同时,会直接转换(trunc)为7。在 Python 中,您可以使用以下方法解决此问题:

int( round(((0.1+0.7)*10)) )

... 在其他语言中也类似。

但是,是的,这在很多情况下都可能是一个问题。例如,浮点数对于薪资程序来说不够可靠。

也许其他人可以给你其他提示。无论如何,希望这会有所帮助。

This is a known problem that has to do with floating point representation, from which you can find more information here:

http://en.wikipedia.org/wiki/IEEE_754-2008

The specific problem is that 7.9 will be directly converted (trunc) to 7 while transforming it to an int. In Python you can solve this with:

int( round(((0.1+0.7)*10)) )

... and similarly in other languages.

But yes, this can be a problem in many situations. Floating point numbers are not reliable enough for payroll programs, for example.

Maybe others can give you other hints. Hpe this helps, anywway.

陌上芳菲 2024-11-23 18:26:19

使用decimal模块:

>>> int((decimal.Decimal('0.1')+decimal.Decimal('0.7'))*10)
8

Use the decimal module:

>>> int((decimal.Decimal('0.1')+decimal.Decimal('0.7'))*10)
8
探春 2024-11-23 18:26:19

PHP默认使用浮点数,需要手动转换为整数。

您应该了解浮点运算。这里的其他帖子提供了足够的链接。

就我个人而言,我使用 round/ ceil/ float 取决于我的期望,而不是 int

$a = (int) round((0.7 + 0.1) * 10);

PHP uses floating point numbers by default, you need to manually cast to integers.

You should be aware of floating point arithmetic. The other posts here provide enough links about that.

Personally I use round/ ceil/ float depending on what I expect as opposed to int

$a = (int) round((0.7 + 0.1) * 10);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文