C++ Builder 10.1 中 double -> unsigned __int64 类型转换的浮点异常
Floating point exception on double -> unsigned __int64 typecast in C++ Builder 10.1
我 运行 遇到一个问题,在 C++ Builder 10.1 Berlin 中某些双精度到无符号 __int64 类型转换抛出浮点无效操作异常($C0000090)。
我的应用程序允许用户输入,因此我需要能够处理任何值,但为简单起见,让我们使用以下示例:
double dValue = 9223372036854775807.0;
unsigned __int64 uhValue = (unsigned __int64) dValue;
虽然我可以在 try/catch 中处理这个异常,但这似乎破坏了 FPU 寄存器堆栈,后续的浮点操作将产生浮点堆栈检查异常。
以下问题报告描述了类似的问题并提供了可能的解决方法:
http://qc.embarcadero.com/wc/qcmain.aspx/qcmain.aspx?d=119745
如果可能的话,我想阻止初始浮点异常。除了精度损失之外,存储在双精度值中的值在有效的无符号 __int64 范围内,因此我无法理解导致异常的原因。
在 typecast/conversion 或异常处理方面,我是否可以做一些不同的事情?
附带说明一下,上面的代码片段在 Visual Studio 中运行良好,并将 uhValue 设置为 9223372036854775808。
谢谢!
我只用旧的BDS2006所以我不能测试你的条件。但是你可以自己加载...像这样:
纯 64 位版本如下所示:
#pragma warn -8056
unsigned __int64 load(double x) // MSb sign(1),exp(11),1.0+mant(52) LSb
{
int exp;
unsigned __int64 y, *q = ((unsigned __int64*)(&x));
exp = (*q >> 52) & 0x7FF; // extract exponent
if (exp == 0x7FF)
return 0; // here handle +/- inf value
else
{ // extract mantissa and debiass exponent
if (exp == 0x00) // denormalized form 0.000001
{
exp = -1024;
y = *q & 0x000FFFFFFFFFFFFF;
}
else
{ // normalized form 1.000001
exp -= 1023;
y = *q & 0x000FFFFFFFFFFFFF;
y |= 0x0010000000000000;
}
}
// update your 64bit value with exponent shift and sign (this part is untested)
exp -= 52;
if (exp > 0)
y <<= +exp;
if (exp < 0)
y >>= -exp;
if (*q >= 0x8000000000000000)
y = -y; // handle sign
return y;
}
#pragma warn .8056
希望我没有做一些愚蠢的事情,因为我无法对其进行测试(我的编译器不支持 64 位算法)代码是从我的 arbnum class double
加载器中获取并更改为满足您的需求。
顺便说一句,我不完全相信 cast 是我之前在项目中遇到过类似问题的问题。我发现自己制作这些的两个主要原因:
使用 OpenGL,其中对 glBegin()/glEnd()
未正确平衡。
缺少 glEnd()
一直在与其无关的代码中抛出 FPU 堆栈异常...
BCB6 继承了 Borland C++ 引擎和编译器错误。
我不使用 BCB6(我在 BDS2006)但是你们证实它也在那里(BCB5 很好),也可能在较新版本的 Borland 中也是如此。编译器生成的简单默认构造函数存在漏洞,对编译器和 C++ 引擎造成严重破坏。结合内存管理器错误(指针的双重删除不会抛出异常,而是使内存管理器无效),您可以随时使指针无效,甚至在不知不觉中覆盖内存中的部分代码......更不用说任何类型的偶然异常(最有可能是访问冲突),但在我深入了解这件事之前,我在某些项目中得到了与您相同的 FPU 废话(顺便说一句,您可以使用单个 fninit
指令来恢复 FPU 偶尔作为最后的手段)。
有关更多信息和解决方法,请参阅:
- bds 2006 C hidden memory manager conflicts
我 运行 遇到一个问题,在 C++ Builder 10.1 Berlin 中某些双精度到无符号 __int64 类型转换抛出浮点无效操作异常($C0000090)。
我的应用程序允许用户输入,因此我需要能够处理任何值,但为简单起见,让我们使用以下示例:
double dValue = 9223372036854775807.0;
unsigned __int64 uhValue = (unsigned __int64) dValue;
虽然我可以在 try/catch 中处理这个异常,但这似乎破坏了 FPU 寄存器堆栈,后续的浮点操作将产生浮点堆栈检查异常。
以下问题报告描述了类似的问题并提供了可能的解决方法: http://qc.embarcadero.com/wc/qcmain.aspx/qcmain.aspx?d=119745
如果可能的话,我想阻止初始浮点异常。除了精度损失之外,存储在双精度值中的值在有效的无符号 __int64 范围内,因此我无法理解导致异常的原因。
在 typecast/conversion 或异常处理方面,我是否可以做一些不同的事情?
附带说明一下,上面的代码片段在 Visual Studio 中运行良好,并将 uhValue 设置为 9223372036854775808。
谢谢!
我只用旧的BDS2006所以我不能测试你的条件。但是你可以自己加载...像这样:
纯 64 位版本如下所示:
#pragma warn -8056
unsigned __int64 load(double x) // MSb sign(1),exp(11),1.0+mant(52) LSb
{
int exp;
unsigned __int64 y, *q = ((unsigned __int64*)(&x));
exp = (*q >> 52) & 0x7FF; // extract exponent
if (exp == 0x7FF)
return 0; // here handle +/- inf value
else
{ // extract mantissa and debiass exponent
if (exp == 0x00) // denormalized form 0.000001
{
exp = -1024;
y = *q & 0x000FFFFFFFFFFFFF;
}
else
{ // normalized form 1.000001
exp -= 1023;
y = *q & 0x000FFFFFFFFFFFFF;
y |= 0x0010000000000000;
}
}
// update your 64bit value with exponent shift and sign (this part is untested)
exp -= 52;
if (exp > 0)
y <<= +exp;
if (exp < 0)
y >>= -exp;
if (*q >= 0x8000000000000000)
y = -y; // handle sign
return y;
}
#pragma warn .8056
希望我没有做一些愚蠢的事情,因为我无法对其进行测试(我的编译器不支持 64 位算法)代码是从我的 arbnum class double
加载器中获取并更改为满足您的需求。
顺便说一句,我不完全相信 cast 是我之前在项目中遇到过类似问题的问题。我发现自己制作这些的两个主要原因:
使用 OpenGL,其中对
glBegin()/glEnd()
未正确平衡。缺少
glEnd()
一直在与其无关的代码中抛出 FPU 堆栈异常...BCB6 继承了 Borland C++ 引擎和编译器错误。
我不使用 BCB6(我在 BDS2006)但是你们证实它也在那里(BCB5 很好),也可能在较新版本的 Borland 中也是如此。编译器生成的简单默认构造函数存在漏洞,对编译器和 C++ 引擎造成严重破坏。结合内存管理器错误(指针的双重删除不会抛出异常,而是使内存管理器无效),您可以随时使指针无效,甚至在不知不觉中覆盖内存中的部分代码......更不用说任何类型的偶然异常(最有可能是访问冲突),但在我深入了解这件事之前,我在某些项目中得到了与您相同的 FPU 废话(顺便说一句,您可以使用单个
fninit
指令来恢复 FPU 偶尔作为最后的手段)。有关更多信息和解决方法,请参阅:
- bds 2006 C hidden memory manager conflicts