将科学计数法中的十进制数转换为 IEEE 754

Posted

技术标签:

【中文标题】将科学计数法中的十进制数转换为 IEEE 754【英文标题】:Converting a decimal number in scientific notation to IEEE 754 【发布时间】:2011-09-15 03:26:34 【问题描述】:

我已经阅读了一些文本和主题,展示了如何从小数转换为 IEEE 754,但我仍然对如何在不扩展小数(以科学记数法表示)的情况下转换数字感到困惑

我特别使用的号码是9.07 * 10^23,但任何号码都可以;我会为我的特定示例弄清楚如何做到这一点。

【问题讨论】:

【参考方案1】:

我假设您希望结果是最接近十进制数的浮点数,并且您使用的是双精度浮点数。

对于大多数数字,有一种方法可以相对快速地完成。简而言之,它的工作原理如下。

您需要将数字拆分为乘积或数字的一部分,这些数字具有精确的浮点数表示。可精确表示的 10 的最大幂是 10^22。因此,要获得浮点形式的 9.07e+23,我们可以这样写:

9.07e+23 = 907 * 10^21

根据 IEEE-754 标准,保证单个浮点运算被正确舍入,因此上述乘积(计算为 2 个双精度浮点数的乘积)将给出正确舍入的结果。

如果您要在转换函数中使用它,您可能会将 10 的幂存储在一个数组中。

请注意,您不能将此方法用于 9.07e-23。这个数字等于 907 / 10^23,因此分母太大而无法精确表示。在这种情况下,以及处理非常大或非常小的数字时,您必须使用某种形式的高精度算术。

有关更多详细信息和示例,请参阅Fast Path Decimal to Floating-Point Conversion。

【讨论】:

【参考方案2】:

如果您知道如何进行 IEEE 浮点加法和乘法运算,那么将数字从十进制字符串转换为二进制 IEEE 是相当简单的。 (或者如果您使用任何基本的编程语言,如 C/C++)

对此有很多不同的方法,但最简单的方法是直接评估9.07 * 10^23

首先,以9.07开头:

9.07 = 9 + 0 * 10^-1 + 7 * 10^-2

现在评估10^23。这可以通过从 10 开始并使用任何功率算法来完成。

然后将结果相乘。

这是一个简单的 C/C++ 实现:

double mantissa = 9;
mantissa += 0 / 10.;
mantissa += 7 / 100.;

double exp = 1;
for (int i = 0; i < 23; i++)
    exp *= 10;


double result = mantissa * exp;

现在,倒退(IEEE -> 十进制)要困难得多。

同样,还有很多不同的方法。这是我能想到的最简单的一个。

我将以1.0011101b * 2^40 为例。 (尾数为二进制)

首先,将尾数转换为十进制:(这应该很容易,因为没有指数)

1.0011101b * 2^40 = 1.22656 * 2^40

现在,“缩放”数字,使二进制指数消失。这是通过乘以 10 的适当幂来“摆脱”二进制指数来完成的。

1.22656 * 2^40 = 1.22656 * (2^40 * 10^-12) * 10^12
               = 1.22656 * (1.09951) * 10^12
               = 1.34861 * 10^12

所以答案是:

1.0011101b * 2^40 = 1.34861 * 10^12

在此示例中,需要 10^12 来“缩小”2^40。确定所需的 10 的幂等于:

power of 10 = (power of 2) * log(2)/log(10)

【讨论】:

您的方法并不总是产生正确的舍入结果。对 9.09e23 试试这个,你会发现9.09e23 - (9 + 9/100.0) * 1e23 不为零。 OP 从未说过它必须正确舍入。您几乎可以肯定需要多精度算术才能正确舍入 - 这是另一个主题......

以上是关于将科学计数法中的十进制数转换为 IEEE 754的主要内容,如果未能解决你的问题,请参考以下文章

将十进制数表示成ieee754标准的32浮点规格化数 27/64

由IEEE 754深入理解浮点数

IEEE 754 转十进制

将十进制转换为 IEEE-754 格式

使用 IEEE 754 标准(32 位)将数字转换为二进制

将 IEEE754 转换为十进制的方程(标准化形式)