手动将 Double 转换为 Float,反之亦然

3 floating-point binary

我知道 double 是 64 位,float 是 32 位:

漂浮:

1 bit for the sign
8 bits for the exponent
24 bits for the fraction
Run Code Online (Sandbox Code Playgroud)

双倍的:

1 bit for the sign
11 bits for the exponent
53 bits for the fraction / mantissa
Run Code Online (Sandbox Code Playgroud)

问题是,我们如何手动将它们相互转换?(我知道精度会丢失)。只是32 bit right shift将 double 转换为 float 吗?并将32 bit left shift浮点数转换为双精度数?

Eri*_*hil 5

将标志放在一边;两种格式都是一样的。

\n\n

如果指数字段全为 1:

\n\n
    \n
  • 数据是无穷大或 NaN。
  • \n
  • 如果有效数字段全为零,则数据为无穷大。返回目标格式的数字,其中包含上面的符号、全 1 的指数字段和全 0 的尾数字段。
  • \n
  • 否则,数据为 NaN。以目标格式返回一个数字,其中包含上面的符号、全为 1 的指数字段以及以某种合理方式更改的尾数(标准未完全定义这一点)。
  • \n
\n\n

如果指数字段既不是全 1 也不是全 0:

\n\n
    \n
  • 将指数字段视为二进制数字(例如,110111 为 103)。减去该格式的偏差(IEEE-754 二进制 32 为 127,二进制 64 为 1023)。这给了你实际的指数。
  • \n
  • 由 \xe2\x80\x9c1.\xe2\x80\x9d 组成一个二进制数,后跟有效数字段的位,例如 \xe2\x80\x9c1.00001111000000000000001\xe2\x80\x9d。这给了你实际的有效数。下面继续。
  • \n
\n\n

如果指数字段全为零:

\n\n
    \n
  • 从 1 开始并减去格式的偏差。这给了你实际的指数。
  • \n
  • 由 \xe2\x80\x9c0.\xe2\x80\x9d 组成一个二进制数,后跟有效数字段的位,例如 \xe2\x80\x9c0.00001111000000000000001\xe2\x80\x9d。这给了你实际的有效数。下面继续。
  • \n
\n\n

如果实际尾数为零,则返回由上面的符号、指数字段中全零以及尾数字段中全零组成的目标格式的数字。

\n\n

如果实际尾数不是以 \xe2\x80\x9c1.\xe2\x80\x9d 开头,则将其左移一位(乘以二)并从实际指数中减一。重复此操作,直到尾数以 \xe2\x80\x9c1 开头。\xe2\x80\x9d

\n\n

如果实际指数等于或超过目标格式的最大有限指数(binary32 为 127,binary64 为 1023):

\n\n
    \n
  • 如果它超过最大有限指数,则返回无穷大,如上所述。
  • \n
  • 如果它恰好等于最大有限指数,则将有效数字舍入为目标格式中的有效位数位数(对于二进制 32 为 24,对于二进制 64 为 53)(使用有效的任何舍入规则,通常舍入到最近的关系) -甚至)。如果这导致它向上舍入为(二进制)\xe2\x80\x9c10.\xe2\x80\x9d,则返回如上所述的无穷大。否则,继续下面。
  • \n
\n\n

如果实际指数等于或超过目标格式的最小正常指数(对于二进制 32 为 \xe2\x88\x92126,对于二进制 64 为 \xe2\x88\x921022):

\n\n
    \n
  • 将有效数字舍入为目标格式中有效数字的位数。
  • \n
  • 从尾数中删除前导 \xe2\x80\x9c1.\xe2\x80\x9d 并使用 \xe2\x80\x9c.\xe2\x80\x9d 之后的位(对于二进制 32 为 23 位,对于二进制 64 为 52 位)来形成有效数编码。
  • \n
  • 将格式的偏差添加到指数以形成偏差指数。
  • \n
  • 返回目标格式的数字,其中包含上面的符号、有偏差的指数和有效数字编码。
  • \n
\n\n

否则,结果不正常(并且可能四舍五入为零):

\n\n
    \n
  • 令 S 为最小正规指数减去实际指数。
  • \n
  • 令 P 为目标格式中有效数字段中的位数(对于二进制 32 为 23,对于二进制 64 为 52)减去 S。(在给定次正规指数的情况下,P+1 是目标格式中有效数的可用位数。它可能为零或负数,但下面的舍入可能会有效地将其变为 1。)
  • \n
  • 将尾数乘以 2 P并将其舍入为整数(使用有效的舍入规则)。
  • \n
  • 返回目标格式的数字,其中包含上面的符号、全零的指数字段以及带有上面舍入有效数字的有效数字字段(采用整数,以二进制表示)。
  • \n
\n