14

最近、私はいくつかの言語でバグ/機能に出くわしました。私はそれがどのように引き起こされるかについて非常に基本的な知識を持っています(そして私はいくつかの詳細な説明が欲しいです)、しかし私が何年にもわたって作ったに違いないすべてのバグを考えるとき、問題はどうやって私が「ねえ、これは引き起こすかもしれないばかげたバグです。任意精度関数を使用したほうがいいです」、他の言語にはこのバグがあります(そして、そうでない言語、理由)。また、なぜ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

ルビー:

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

7 に答える 7

7

言語の問題ではありません。これは、浮動小数点演算の一般的な問題です。

于 2011-06-22T11:41:00.530 に答える
5

フロートの使用を停止します。いいえ、本当に。

于 2011-06-22T11:40:38.917 に答える
3

数値の浮動小数点表現は正確ではありません

Pythonでは、intはfloatをゼロに向かって最も近い整数に 切り捨てます。(int)PHP、parseIntJavascript、to_iRubyでも同じことをします。

これはバグではありません。これらの関数がどのように機能するかです。

たとえば、Pythonのドキュメントintから:

浮動小数点数の整数への変換は(ゼロに向かって)切り捨てられます。

于 2011-06-22T11:41:32.480 に答える
1

これは浮動小数点表現に関係する既知の問題であり、ここから詳細情報を見つけることができます。

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

特定の問題は、7.9がintに変換されるときに、7.9が7に直接変換(切り捨て)されることです。Pythonでは、次の方法でこれを解決できます。

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

...そして他の言語でも同様です。

しかし、はい、これは多くの状況で問題になる可能性があります。たとえば、浮動小数点数は給与プログラムには十分な信頼性がありません。

多分他の人があなたに他のヒントを与えることができます。とにかく、これは役に立ちます。

于 2011-06-22T11:45:25.107 に答える
1

decimalモジュールを使用します。

>>> int((decimal.Decimal('0.1')+decimal.Decimal('0.7'))*10)
8
于 2011-06-22T11:50:01.000 に答える
0

PHPはデフォルトで浮動小数点数を使用するため、手動で整数にキャストする必要があります。

浮動小数点演算に注意する必要があります。ここの他の投稿はそれについての十分なリンクを提供します。

個人的には、intではなく、期待する内容に応じて、round / ceil/floatを使用します。

$a = (int) round((0.7 + 0.1) * 10);
于 2011-06-22T11:45:21.320 に答える