int((0.1+0.7)*10) = 7 in several languages. How to prevent this?

本小妞迷上赌 提交于 2019-12-17 04:01:53

问题


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                                                    

回答1:


What Every Computer Scientist Should Know About Floating-Point Arithmetic




回答2:


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




回答3:


Stop using floats. No, really.




回答4:


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).




回答5:


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.




回答6:


Use the decimal module:

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



回答7:


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);


来源:https://stackoverflow.com/questions/6439140/int0-10-710-7-in-several-languages-how-to-prevent-this

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!