【问题标题】:Bitwise conversion of int64 to IEEE double?int64到IEEE double的按位转换?
【发布时间】:2020-11-23 03:11:21
【问题描述】:

我正在尝试查找或找出将带符号的 64 位 int(二进制补码,natch)转换为最接近的值 IEEE double(64 位)的算法,保持按位运算。我在寻找什么for 用于通用的“类 C”伪代码;我正在一个不是 C 且没有本机 int64 类型的平台上实现一个玩具 JVM,所以我在 8 字节数组上进行操作(幸运的是,它的细节超出了这个范围),这就是域数据需要保留。

所以:输入是一个 64 位的大端字符串,带符号的二进制补码。输出是 IEEE 双格式的 64 位大端字符串,表示尽可能接近原始 int64 值。中间是一些面具,班次等!算法绝对不需要特别聪明或优化。我只是希望能够得到结果并理想地了解过程是什么。

因为我怀疑这是一个不寻常的需求,所以无法追踪到这个。 This answer 解决了 x86 SSE 中的一个平行问题(我认为),但我不会说 SSE,我的尝试和翻译让我更加困惑而不是开明。

希望有人指出正确的食谱方向,或者理想地解释背后的按位数学,以便我真正理解它。谢谢!

【问题讨论】:

  • 您有关于转换的具体问题吗?得到尾数是微不足道的,你可以通过“最高设置位”对数近似得到指数,对吧?
  • @CarlNorum:不幸的是,你已经有点失去我了。我理解 double 的按位分量在理论上代表什么,但我对如何填充这些位以反映 int64 的最准确表示非常模糊。 (保存很明显的符号位。)当你说尾数是微不足道的..你能给我另一个提示吗? :) 我也不熟悉最高设置位对数近似,但我会继续寻找。谢谢
  • 有效位将与您现有的 64 位 int 具有相同的(二进制)数字。它已经是二的幂数。
  • 好的,我写了一个基本的(可能很糟糕)实现。让我整理一下,我会写一个答案。

标签: c double bit-manipulation ieee-754 int64


【解决方案1】:

这是一个简单的(在几个方面是错误的)实现,包括一个测试工具。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

double do_convert(int64_t input)
{
    uint64_t sign = (input < 0);
    uint64_t magnitude;

    // breaks on INT64_MIN
    if (sign)
        magnitude = -input;
    else
        magnitude = input;    

    // use your favourite algorithm here instead of the builtin
    int leading_zeros = __builtin_clzl(magnitude);
    uint64_t exponent = (63 - leading_zeros) + 1023;
    uint64_t significand = (magnitude << (leading_zeros + 1)) >> 12;

    uint64_t fake_double = sign << 63
                         | exponent << 52
                         | significand;

    double d;
    memcpy(&d, &fake_double, sizeof d);

    return d;
}

int main(int argc, char** argv)
{
    for (int i = 1; i < argc; i++)
    {
        long l = strtol(argv[i], NULL, 0);
        double d = do_convert(l);
        printf("%ld %f\n", l, d);
    }

    return 0;
}

这里的损坏很多 - 基本思想是首先提取符号位,然后将数字视为正数,如果输入为 INT64_MIN,则将不起作用。它也不能正确处理输入0,因为在这种情况下它不能正确处理指数。这些扩展留给读者作为练习。 ;-)

无论如何 - 该算法只是通过计算输入数字的 log2 并偏移 1023 (because floating point) 来计算指数,然后通过将数字向上移动足够远以丢弃最高有效位,然后移动来获得有效数字回到正确的场地位置。

毕竟,最终双精度的组装非常简单。

编辑:

谈到读者的练习 - 我也使用 _builtin_clzl() 实现了这个程序。您可以根据需要扩展该部分。

【讨论】:

  • 太好了,非常感谢。这是我需要的开始,我将弄清楚如何适应和处理极端情况。非常感谢。
  • 希望这一切都是合理的。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多