【发布时间】:2020-04-24 11:02:28
【问题描述】:
我正在尝试手动实现双精度和 128 位整数之间的乘法,这是我使用两个 ulong 创建自己的。
我的理解如下:
1. 将双精度数分解为有效数和指数。确保有效数字是normalized。
2. 将有效数字与我的 uint128 相乘。这会给我 256 位数。
3. 将我的 256 位数按从双精度中提取的指数移位。
4.如果值超过128位,那么我溢出了。
我觉得我非常接近,但我错过了一些东西。可以说我有以下示例。我正在存储一个值为 2^127 的 uint128,我想将它乘以 8E-6。
uint128 myValue = new uint128(2^127);
double multiplier = 8E-6;
uint128 product = myValue * multiplier;
真正的价值或正确答案是1361129467683753853853498429727072.845824。
所以我想将值 1361129467683753853853498429727072 作为我的 128 位整数。
问题是我的实现给了我1361129467683753792259819967610881。
int exponent; // This value ends up being -69 for 8E-6
uint128 mantissa = GetMantissa(multiplier, out exponent); // This value ends up being 4722366482869645 after normalizing it.
uint256 productTemp = myValue * mantissa; // This value is something like 803469022129495101412490705402148357126451442021826560.
uint128 product = productTemp >> exponent. // this value is 1361129467683753792259819967610881
我正在使用来自extracting mantissa and exponent from double in c# 的代码来获取我的尾数和指数。我可以使用这些值正确地将 8E-6 作为双精度返回。
有人知道我在这里做错了什么吗?如果我使用 .8 而不是 8E-6,我的值会更好。
【问题讨论】:
-
你在这里展示的是什么编程语言?
-
C# 是我正在编写的,但只要使用 IEEE 754 浮点双精度,该语言就不太相关。我写了我自己的 UInt128,我自己处理 256 位的乘法,以及双精度的分解。
-
退一步看大局,我知道您已经有了一个可以得到您想要的结果的数据类型,System.Decimal,但您希望获得更好的性能。通常,最大的一步是在硬件实现和软件实现之间。你确定你会获得足够的性能提升来证明这项工作的合理性吗?
-
@PatriciaShanahan 我不是。 System.Double 的性能明显快于 System.Decimal 的性能,但 System.Double 可能不足以满足我需要的精度。我正在查看针对特定值范围的一组特定操作。我认为最终,我不会更快,但我需要有有效的代码来进行基准测试,以便自信地展示它。
标签: math floating-point double