C++ 从双精度到无符号long-long的转换失败

C++ 从双精度到无符号long-long的转换失败,c++,floating-point,type-conversion,C++,Floating Point,Type Conversion,基于这个问题,我想出了一个可移植的安全方法,将浮点类型转换为整数数组,代码运行良好,但对于某些值,当从double转换为无符号长时,精度可以用无符号长安全表示,转换失败的原因不是编译时错误,而是无效值,即有符号长的最小可表示值或零,在Visual C++ 2008、英特尔XE 2013和GCC 4.7.2. 转换失败。 代码如下:(注意中的第一条语句,而main函数中的循环) \ifndef字符位 #包括 #恩迪夫 #包括 #包括 typedef签名int int32; typedef签名的lo

基于这个问题,我想出了一个可移植的安全方法,将浮点类型转换为整数数组,代码运行良好,但对于某些值,当从
double
转换为
无符号长
时,精度可以用
无符号长
安全表示,转换失败的原因不是编译时错误,而是无效值,即
有符号长
的最小可表示值或零,在Visual C++ 2008、英特尔XE 2013和GCC 4.7.2.

转换失败。 代码如下:(注意
中的第一条语句,而
main
函数中的
循环)

\ifndef字符位
#包括
#恩迪夫
#包括
#包括
typedef签名int int32;
typedef签名的long-long-int64;
typedef无符号整数uint32;
typedef无符号长uint64;
typedef float float32;
typedef双浮点数64;
//获取与字符位对应的类型大小(以位为单位)。
模板
结构尺寸
{
静态常数uint32值=sizeof(t)*字符位;
};
//阶乘函数
浮动64 fct(int32 i)
{
r=1;
dor*=i;而(--i>1);
返回r;
}
int main()
{
//uint32中可存储的最大2对电源
const uint32 power_2=uint32(~0);
//幂_2中的二进制位数
const uint32 digit\u cnt=sizeof\u ex::value;
//将存储扩展值的数组元素数
const uint32 comp\u count=DBL\u MAX\u EXP/数字\u cnt+uint32((DBL\u MAX\u EXP/数字\u cnt)*数字\u cnt0)
{
//存储当前部件
//在这一行中,编译器失败
值[启动指数]=uint64(f/功率指数2);
//从f中排除它
f-=幂2*64(值[开始指数]);
//减量指数
--启动索引;
}
//得到最后一部分
值[0]=uint32(f);
}
上面的转换代码将给出不同的编译器之间的结果,这意味着当阶乘函数的参数为20时,所有编译器返回有效结果,当值大于20时,一些编译器得到部分结果,而其他编译器没有,当值变大时,例如
35
它变为零

请告诉我为什么会发生这些错误


谢谢。

我认为您的转换逻辑没有任何意义

您有一个名为“power_2”的值,它实际上不是2的幂,尽管有评论说它是

通过除以小于32位的值,可以提取非常大(>64位)数的位。显然,结果将是>32位,但您将其存储为32位值,并将其截断。然后你将它乘以原始除数,然后从浮点数中减去。但是,当数字被截断时,减去的值比原始值小得多,这几乎肯定不是您所期望的

我认为更错误的是,你并不总是想要最上面的32位,对于一个不是32位长倍数的数字,你想要的是实际长度mod 32

这里有一个对你的代码有点懒惰的黑客,它做了我认为你要做的事情。请注意,
pow()
可以进行优化

while (start_index > 0)
{
    float64 fpow = pow(2., 32. * start_index);
    // store current part
    // in this line the compiler fails

    value[start_index] = f / fpow;
    // exclude it from f

    f -= fpow * float64(value[start_index]);
    // decrement index
    --start_index;
}

这几乎没有经过测试,但希望能说明我的意思。

我已经更改了很多代码,直到我忘记更新注释以表达我的意思,非常感谢您的帮助。
while (start_index > 0)
{
    float64 fpow = pow(2., 32. * start_index);
    // store current part
    // in this line the compiler fails

    value[start_index] = f / fpow;
    // exclude it from f

    f -= fpow * float64(value[start_index]);
    // decrement index
    --start_index;
}