我正在尝试使用C#中的显式强制转换运算符将BigInteger值转换为双精度值,但是没有得到我预期的收敛舍入行为。我找不到关于此操作的舍入模式的任何文档,但它与long to double cast(也未记录)的文档不匹配。错误或功能?我已经实现了自己的舍入程序来解决它,但宁可坚持使用内置功能。</ p>
这是一个经过编写的测试(Windows 7上的VS 2012):
BigInteger roundMeDown = BigInteger.Pow(2, 53) + 1;
double expectedRoundedDown = Math.Pow(2, 53);
BigInteger roundMeUp = BigInteger.Pow(2, 53) + 3;
double expectedRoundedUp = Math.Pow(2, 53) + 4;
double actualResult = Math.Pow(2, 53) + 2;
Assert.AreEqual(expectedRoundedDown, (double)roundMeDown);
Assert.AreNotEqual(expectedRoundedUp, (double)roundMeUp);
Assert.AreEqual(actualResult, (double)roundMeUp);
答案 0 :(得分:1)
http://referencesource.microsoft.com/#System.Numerics/System/Numerics/BigInteger.cs
有实际的源代码,它会告诉你它是如何做到的。
简而言之,它看起来基本上是在切换和移位,而根本没有任何四舍五入。请注意,它调用了一个名为GetApproxParts
的方法。
但是,如果你需要特殊的舍入,最后应该很容易入侵。
基本上,只需使用NumBits - 53
和>>
运算符查看BigInteger上的|
rd位(从最重要到最不重要)(双尾数在尾数中有52位)。
基本上有三种情况,根据您可能想要使用的不同舍入模式,只有最后一种处理方式不同。
如果未设置第53位,则无需舍入。
如果是,请检查后面的位。如果设置了任何一个,则向上舍入(添加Double.Epsilon)。
如果已设置且设置后没有位,则正好位于两个有效双精度值的中间。做任何合理的事情,只要它是一致的。