2011-02-20 15 views
3

誰かが次のように説明できますSystem.Numerics.BigIntegerこのMath.Log10とBigInteger.Log10の動作を説明できますか?

Console.WriteLine(Math.Log10(100));  // prints 2 
Console.WriteLine(Math.Log10(1000));  // prints 3 (as expected) 

Console.WriteLine((int)Math.Log10(100)); // prints 2 
Console.WriteLine((int)Math.Log10(1000)); // prints 3 (as axpected) 

var bi100 = new BigInteger(100); 
var bi1000 = new BigInteger(1000); 

Console.WriteLine(BigInteger.Log10(bi100));  // prints 2 
Console.WriteLine(BigInteger.Log10(bi1000));  // prints 3 (as axpected) 

Console.WriteLine((int)BigInteger.Log10(bi100)); // prints 2 
Console.WriteLine((int)BigInteger.Log10(bi1000)); // prints 2 ??????? 

Console.WriteLine(Math.Floor(BigInteger.Log10(bi100))); // prints 2 
Console.WriteLine(Math.Floor(BigInteger.Log10(bi1000))); // prints 2 ??????? 

Console.WriteLine(Math.Round(BigInteger.Log10(bi100))); // prints 2 
Console.WriteLine(Math.Round(BigInteger.Log10(bi1000))); // prints 3 (as expected) 

EDIT:私はそれがrouding問題だということを知っていることに注意してください。私は知りたいなぜ Math.Log10とBigInteger.Log10の動作が異なるのですか?

+0

最後の行にはコードコメントが正しくありません:少なくとも3のために印刷してください –

+0

@Mitch:修正済みです。 – schnaader

答えて

6

精度と丸めによるものです。

この行:Console.WriteLineはこれを書いているのに対し、

Console.WriteLine((int)BigInteger.Log10(bi1000)); 

あなたは中間double変数を使用して、その値を検査し、これを確認することができ3

として、2値2.9999999999999996を切り捨てています。

double x = BigInteger.Log10(bi1000); 
Console.WriteLine((int)x); 
+1

コメントを残してください。ありがとう。 –

+2

+1これは正解であるため – schnaader

+1

-1 "3はバイナリとして正確に表現できません"は完全に偽です。すべてのオペランドも正確です。しかし、中間値のいくつかは、対数関数がどのように実装されているかに応じて、不正確かもしれません。 –

-1

動作が異なるのは、表現が異なり、タイプが異なるためです。異なる実装。 Math.Log10(x)が(それはexternだので、それを把握することは容易ではありません)異なる方法で実装されるのに対し、

+0

(CWは悪い質問に対する悪い回答ですので) – Zooba

+0

なぜそれは悪い質問ですか? –

+1

丸めの問題については、幸いなことに終わりはありません。 –

1

大きな違いは、BigInteger.Log10(x)Math.Log(x)/Math.Log(10)として実装されていることです。それにもかかわらず、それらが10進数の対数を行うためにわずかに異なるアルゴリズムを使用していることは明らかです。

関連する問題