你能解释一下这个Math.Log10与BigInteger.Log10的行为吗?

时间:2011-02-20 01:26:38

标签: c# .net floating-point biginteger

有人可以解释以下System.Numerics.BigInteger行为吗?

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)

编辑:请注意,我知道这是一个问题。我想知道为什么 Math.Log10和BigInteger.Log10的行为不同。

3 个答案:

答案 0 :(得分:6)

这是由于精确和圆整。

这一行:

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

将值2.9999999999999996向下舍入为2,而Console.WriteLine将其写为3

您可以使用中间double变量对其进行验证,并检查其值:

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

答案 1 :(得分:1)

最大的区别在于BigInteger.Log10(x)实现为Math.Log(x)/Math.Log(10),而Math.Log10(x)实现方式不同(它是extern,所以要弄清楚并不容易)。无论如何,显而易见的是,它们使用稍微不同的算法来进行基数为10的对数,这会导致输出略有差异。

答案 2 :(得分:-1)

行为不同,因为它们是具有不同表示和不同实现的不同类型。