我正在尝试在 .NET 中创建“BigDouble”结构。BigDouble 数具有 BigInteger 整数部分和双小数部分。
实现加法和减法很简单,但是如何进行乘法/除法?问题是我找不到将 BigInteger 与 double 相乘的方法。我应该怎么办?
请记住:我需要一个精确的底数和一个近似的小数部分。
我正在尝试在 .NET 中创建“BigDouble”结构。BigDouble 数具有 BigInteger 整数部分和双小数部分。
实现加法和减法很简单,但是如何进行乘法/除法?问题是我找不到将 BigInteger 与 double 相乘的方法。我应该怎么办?
请记住:我需要一个精确的底数和一个近似的小数部分。
双精度数具有固定数量的 mantiassa 位和一个指数。根据 IEEE 规范,mantiassa 将有 52 位,并且小数点前的 bis 被省略但始终为 1。因此实际上您至少有 53 位小数点后的信息。如果你很幸运并且小数部分很小,你可能会有更高的分辨率,但如果整数部分不为零,这似乎不太可能。
因此,一种解决方案是将小数部分乘以 2 53并将其四舍五入为整数。然后您可以使用这些缩放值进行计算,使用它们来形成更大的整数,然后再按比例缩小。如果您想不惜一切代价避免数据丢失,则必须确定数字的指数double
并相应地进行缩放。我知道其他语言中的一些函数,例如Math.getExponent
Java 或ilogb
C 中的函数。我猜想 .net 中也有类似的东西,但我不知道。
但是这整个观察告诉我(也可能告诉你)adouble
可能不是存储小数部分的合适方法。的优势double
在于它的浮点数:您可以使用不断变化的指数来存储极小和极大的值。但是,在您的应用程序中,您将以大约相等的概率(或者我假设)存储范围 [0,1) 中的值。double
因此,没有使用的主要力量。我猜你最好使用基于BigInteger
. 我建议使用小数点后的 64 位。存储要求将与您的方法相同,因为double
需要 64 位。但在大多数情况下,精度将提高约 11 位,因为您可以将所有 64 位用于有用的数字,而不是在您的方法中仅使用 53 位。而且性能也会好很多,因为您不必在格式之间进行转换。