双精度浮点型转整型时数据溢出,与x86平台表现不一致
现象描述
C/C++双精度浮点型数转整型数据时,如果超出了整型的取值范围,鲲鹏平台的表现与x86平台的表现不同 。
long aa = (long)0x7FFFFFFFFFFFFFFF; long bb; bb = (long)(aa*(double)10); // long->double->long //x86: aa=9223372036854775807, bb=-9223372036854775808 //arm64:aa=9223372036854775807, bb=9223372036854775807
问题原因
在两个平台下,是两套CPU架构,其中的算数逻辑单元的实现可能会有差异,操作系统、编译器的实现都会有所不同。x86(指令集)中的浮点到整型的转换指令,定义了一个indefinite integer value——“不确定数值”(64bit:0x8000000000000000),大多数情况下x86平台确实都在遵循这个原则,但是在从double向无符号整型转换时,又出现了不同的结果。鲲鹏的处理则非常清晰和简单,在上溢出或下溢出时,保留整型能表示的最大值或最小值,开发者并不会面对不确定或无法预期的结果。
处理步骤
参考如下数据转换的表格,调整代码中的实现。
double型数据向long转换:
CPU |
double值 |
转为long变量保留值 |
说明 |
---|---|---|---|
x86 |
正值超出long范围 |
0x8000000000000000 |
indefinite integer value |
x86 |
负值超出long范围 |
0x8000000000000000 |
indefinite integer value |
鲲鹏 |
正值超出long范围 |
0x7FFFFFFFFFFFFFFF |
鲲鹏为long变量赋值最大的正数 |
鲲鹏 |
负值超出long范围 |
0x8000000000000000 |
鲲鹏为long变量赋值最小的负数 |
double数据向unsigned long转换:
CPU |
double值 |
转为unsigned long变量值 |
说明 |
---|---|---|---|
x86 |
正值超出long范围 |
0x0000000000000000 |
x86为long变量赋值最小值0 |
x86 |
负值超出long范围 |
0x8000000000000000 |
indefinite integer value |
鲲鹏 |
正值超出long范围 |
0xFFFFFFFFFFFFFFFF |
鲲鹏为unsigned long变量赋值最大值 |
鲲鹏 |
负值超出long范围 |
0x0000000000000000 |
鲲鹏为unsigned long变量赋值最小值 |
double数据向int转换:
CPU |
double值 |
转为int变量值 |
说明 |
---|---|---|---|
x86 |
正值超出int范围 |
0x80000000 |
indefinite integer value |
x86 |
负值超出int范围 |
0x80000000 |
indefinite integer value |
鲲鹏 |
正值超出int范围 |
0x7FFFFFFF |
鲲鹏为int变量赋值最大的正数 |
鲲鹏 |
负值超出int范围 |
0x80000000 |
鲲鹏为int变量赋值最小的负数 |
double数据向unsigned int转换:
CPU |
double值 |
转为unsigned int变量值 |
说明 |
---|---|---|---|
x86 |
正值超出unsigned int范围 |
double整数部分对2^32取余 |
x86为unsigned int变量赋值最小的负值 |
x86 |
负值超出unsigned int范围 |
double整数部分对2^32取余 |
x86为unsigned int变量赋值最小的负值 |
鲲鹏 |
正值超出unsigned int范围 |
0xFFFFFFFF |
鲲鹏为unsigned int变量赋值最大的正数 |
鲲鹏 |
负值超出unsigned int范围 |
0x00000000 |
鲲鹏为unsigned int变量赋值最小的负数 |