Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C int64到IEEE double的位转换?_C_Double_Bit Manipulation_Ieee 754_Int64 - Fatal编程技术网

C int64到IEEE double的位转换?

C int64到IEEE double的位转换?,c,double,bit-manipulation,ieee-754,int64,C,Double,Bit Manipulation,Ieee 754,Int64,我试图找到或弄清楚将有符号64位int(twos-complete,natch)转换为最接近的值IEEE-double(64位)的算法,保持按位操作;我在一个不是C的平台上实现了一个玩具JVM,并且没有本机的int64类型,所以我在8字节数组上操作(幸运的是,这些数组的细节超出了这个范围),而这正是数据需要保留的域 所以:输入是一个64位的大端字符串,有符号的两位补码。输出是IEEE双精度格式的64位大端字符串,表示尽可能接近原始int64值。中间是一组面具、轮班等等!算法绝对不需要特别聪明或优

我试图找到或弄清楚将有符号64位int(twos-complete,natch)转换为最接近的值IEEE-double(64位)的算法,保持按位操作;我在一个不是C的平台上实现了一个玩具JVM,并且没有本机的
int64
类型,所以我在8字节数组上操作(幸运的是,这些数组的细节超出了这个范围),而这正是数据需要保留的域

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

因为我怀疑这是一个不寻常的需求,所以很难找到它。在x86 SSE中解决了一个类似的问题(我想),但我不会说SSE,我的尝试和翻译让我更加困惑而不是开悟

我希望有人能为食谱指出正确的方向,或者最好能解释一下背后的逐位数学,这样我才能真正理解它。谢谢

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

#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;
}
#包括
#包括
#包括
双do_转换(int64_t输入)
{
uint64_t符号=(输入<0);
uint64级;
//在INT64_MIN上中断
如果(签名)
幅值=-输入;
其他的
幅值=输入;
//在这里使用您最喜欢的算法,而不是内置算法
int前导零=uuu内置clzl(幅值);
uint64指数=(63-前导零)+1023;
uint64有效位=(震级>12;

uint64\u t fake\u double=sign您对转换有什么具体问题吗?获取尾数很简单,通过“最高设定位”可以获得指数对数近似,对吗?@CarlNorum:不幸的是,你已经有点迷糊了。我知道双精度的按位分量在理论上代表什么,但我对如何填充这些位来反映int64的最精确表示非常模糊。(保留明显的符号位。)当你说尾数是微不足道的。你能给我另一个提示吗?:)我也不熟悉最高集位对数近似,但我会继续寻找。有效位将与现有的64位整数具有相同的(二进制)数字。它已经是两个数的幂。好的,我写了一个基本(可能不好)实施。让我整理一下,然后我会写一个答案。太好了,非常感谢。这是我需要的开始,我会找出如何适应和处理角落案例。非常感谢。希望这一切都是合理的。:-)