2017-06-28 11 views
0

これは何度も尋ねられていますが、私は多くのブログとその答えに出くわしましたが、これは私が私の髪を引っ張るようにしています。私はちょうどので、私はその小数を取り除く100で2進数を乗算します:Python DecimalとC#の小数精度

>>> 4321.90 * 100 
432189.99999999994 
>>> Decimal(4321.90) * Decimal(100) 
Decimal('432189.9999999999636202119291') 

私は、このような一見些細な操作に丸め使用して怖いです。それは安全でしょうか?精密な問題が私のトリックを演じ、その結果がxxx.5に近ければどうなるでしょうか?それは起こることができますか?私は、バイナリレベルでの問題を理解しますが、私は、C#から来て、私は、.NETのdecimalタイプでその問題を持っていない:

decimal x = 4321.90m; 
decimal y = 100m; 
Console.WriteLine(x * y); 
432190,00 

私はPythonのdecimalモジュールは、これを修正することになったと思いました。私は初期値を文字列に変換しようとしていますが、文字列操作で数学を行います。

+3

リテラル '4321.90'バイナリフロートは関係なく、それがどのように表示されるコンテキストではありません。つまり、あなたが渡している小数点以下の値を 'Decimal()'コンストラクタに渡すことはありません。代わりに 'Decimal(" 4321.90 ")'という綴りを付けてください。 –

+0

これは常に小数点以下の2桁の数字です。文字列に変換し、ドット '。'を置き換えます。何もない。 –

+0

@ Ev.Kounisこれは文字列操作であり、私はむしろこれをやっていません。 – Jerther

答えて

3

4321.90はfloatと解釈されるため、その時点で)、実行時にDecimalにキャストされます。 C#4321.90mは、最初に10進数として解釈されます。 Pythonは小数点をビルトイン構造としてサポートしていません。

しかし、Pythonでそれを修正する簡単な方法があります。単純に文字列を使用してください:

>>> Decimal('4321.90') * Decimal('100') 
Decimal('432190.00') 
+0

どのような場合でも、初期値は文字列でなければならず、ユーザー入力、データベースクエリ、ハードコーディングのいずれであってもDecimal()に渡されます。右? – Jerther

+1

@Jertherまさしく、安全に(あるいは正確に) 'Decimal'を初期化するためには文字列が必要です。 – freakish

+0

トリックもうまくいくDecimal(repr(4321.90))もあります。 https://stackoverflow.com/a/18886013/2498426 – Jerther

1

Floating point inaccuracy again

Decimal(number)の前に値が変更されます。の前に、Decimalがヒットします。

Decimal("4321.90") * Decimal("100") 

結果:あなたはDecimalに文字列を渡すことにより、ただしことを避けることができる

のでDecimalは、浮動小数点を使用せずに、浮動小数点数を扱う(

Decimal('432190.00') 

は全く&の操作を登録します)

2

rt初期値を文字列に変換

はい!

をし、文字列操作

ないで計算を行う - (文字列リテラルを使用しますが、strを呼び出すことによって、それをしません)!

ソースコードに10進数値をハードコーディングする場合は、浮動小数点リテラルではなく文字列リテラルから初期化する必要があります。 4321.90では、浮動小数点の丸めが既に発生しており、Decimalを構築しても元に戻すことはできません。 "4321.90"では、10進あなたは、正確な初期化を実行するために利用できる書いたオリジナルテキストを持っています

Decimal('4321.90')