double上的浮点异常 - > C ++ Builder 10.1

时间:2017-03-23 18:42:59

标签: casting c++builder floating-point-exceptions

我遇到了一个问题,即C ++ Builder 10.1中的某些双重无符号__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

如果可能的话,我想阻止初始浮点异常。除了精度损失之外,存储在double中的值在有效的无符号__int64范围内,因此我无法理解导致异常的原因。

在涉及到类型转换/转换或异常处理时,我有什么不同的做法吗?

作为旁注,上面的代码片段在Visual Studio中运行正常,并将uhValue设置为9223372036854775808。

谢谢!

1 个答案:

答案 0 :(得分:0)

我只使用旧的 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类double加载器并根据您的需要进行更改。

BTW我并不完全相信演员是我在以前的项目中遇到过类似问题的问题。我找到了两个主要原因:

  1. 使用 OpenGL ,其中glBegin()/glEnd()对未正确平衡。

    缺少glEnd()在不相关的代码中一直抛出FPU堆栈异常......

  2. BCB6 继承了 Borland C ++ 引擎和编译器错误。

    我不使用 BCB6 (我在 BDS2006 ),但你们确认它也在那里( BCB5 很好)也可能在更新版本的Borland中。简单地说,编译器生成的默认构造函数会对编译器和 C ++ 引擎造成严重破坏。结合内存管理器错误(指针的双重删除不会抛出异常但会使内存管理器无效),您可以在任何时候无意中覆盖内存中的部分代码而使指针无效...更不用说任何类型的偶然异常(最可能的)是访问违规)但是在我得到这个东西的底部之前,我得到了一些像你一样的 FPU 废话(顺便说一句,你可以使用单fninit指令恢复 FPU 不时作为最后的手段)。

    有关详细信息以及如何解决,请参阅: