从整数到浮点的转换如何工作?

Posted

技术标签:

【中文标题】从整数到浮点的转换如何工作?【英文标题】:How does conversion from integer to floating-point work? 【发布时间】:2014-05-12 19:52:41 【问题描述】:

每种编程语言都有自己的方法将整数转换为浮点数,将 01010 转换为其他 01010。 如果您看到 ASM 生成的代码,它会使用协处理器指令向用户隐藏真实值。

但它在现实中是如何工作的?尾数、指数算法如何计算?

【问题讨论】:

演员表是一种句法结构,如(float)。没有“自动施法”之类的东西。你的意思是“转化”。 是的,但我的意思是执行什么过程将整数转换为浮点数 如果有 4 个人对我的问题投了赞成票,我不明白为什么有多少人反对我的问题.. 你看不出一个问题怎么会被认为是坏的,而对同一个问题的回答是好的?假设性问题如此模糊以至于难以回答,没有研究,语法很差怎么办?这样的问题仍然可以得到明确的、解释性的、权威的答案,但仍然是一个糟糕的问题。 【参考方案1】:

如果您知道浮点格式,您应该能够自己计算出算法。

    如果输入为 0,则结​​果全为 0 位。 如果输入为负,则将符号位设置为 1,并对输入进行补码。 查找最高位集。将偏差添加到其索引中,这将是您的指数。 清除最高位设置,剩下的是尾数。

由于此问题已被标记为 assembly,因此这里是 x86 的示例实现:

int_to_float:
    xor eax, eax
    mov edx, [esp+4]
    test edx, edx
    jz .done
    jns .pos
    or eax, 0x80000000 ; set sign bit
    neg edx
.pos:
    bsr ecx, edx
    ; shift the highest bit set into bit #23
    sub ecx, 23
    ror edx, cl         ; works for cl < 0 too
    and edx, 0x007fffff ; chop off highest bit
    or eax, edx         ; mantissa
    add ecx, 127 + 23   ; bias
    shl ecx, 23
    or eax, ecx         ; exponent
.done:
    ret

注意:这将返回 eax 中的浮点数,而调用约定通常要求 st0。我只是想完全避免使用 FPU 代码。

【讨论】:

【参考方案2】:

将整数转换为浮点数时,它只是移位,直到尾数在正确的范围内,即 1

例如,数字 1010 被移动直到它是 1.010 并且指数是 3 因为这是它被移动了多少位。

尾数的第一个数字,小数点分隔符之前的1,不存储在数字中,因为它始终是一个。 (零值被视为单独的情况。)

指数(对于双精度数)存储的偏移量为 1023 (001111111111),因此指数 3 存储为 1026 (010000000010)。

这使得1010 表示为双精度浮点数:

010000000010 010 0000000000000000000000000000000000000000000000000

010 之后的所有零都用于填充剩余的 52 位尾数。


您可以在此处阅读有关浮点格式的更多信息:Wikipedia: Double-precision floating-point format

【讨论】:

【参考方案3】:

对于 32 位 ints、64 位 int64s 和 IEEE 64 位 doubles,以下技巧有效(除了违反别名规则等):

double convert(int x) 
  double tricky = 0x1.8p53;
  int64 hack = (int64 &)tricky + x;
  return (double &)hack - 0x1.8p53;

我在这里接受tricky = 2^53 + 2^52。此值的最小可表示变化是1,这意味着有效数字以1 为单位测量。有效数字存储在double 的低52 位中。我不会通过添加x 来溢出或下溢有效位(因为x 是32 位),所以hack2^53 + 2^52 + x 的二进制表示为double。减去2^53 + 2^52 得到x,但作为double

(我认为接下来的代码有点接近 x86-64 汇编代码。我不明白为什么它不会做正确的事情,但我没有测试它。甚至没有组装它。)

movsx rax, dword ptr [x]
add rax, [tricky]
mov [hack], rax
fld [hack]
fsub st(0), [tricky]
fstp [answer]

【讨论】:

这个 hack 和这个 ***.com/questions/17035464/… 有关系吗? @LưuVĩnhPhúc:是的!正好相反。

以上是关于从整数到浮点的转换如何工作?的主要内容,如果未能解决你的问题,请参考以下文章

将整数转换为新的浮点格式

归一化整数到/从浮点转换

如何将浮点值转换为具有精确精度的整数,例如 123.3443 到 1233443?

带有溢出的 ARM Neon 浮点整数转换的行为

避免浮点运算

字节数组byte[]和整型,浮点型数据的转换——Java代码