1

我在 C++ Builder 10.1 Berlin 中遇到了某些 double 到 unsigned __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。

谢谢!

4

1 回答 1

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加载器并根据您的需要进行更改。

顺便说一句,我并不完全相信演员阵容是我之前在项目中遇到过类似问题的问题。我发现自己生产这些的主要原因有两个:

  1. 在对未正确平衡的情况下使用 OpenGL 。glBegin()/glEnd()

    MissingglEnd() 一直在与它无关的代码中抛出 FPU 堆栈异常......

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

    我不使用BCB6(我在BDS2006上),但你们确认它也存在(BCB5很好),并且可能也在较新版本的 Borland 中。编译器生成的简单的默认构造函数存在错误,对编译器和C++引擎造成严重破坏。结合内存管理器错误(指针的双重删除不会引发异常,而是使内存管理器无效),您可以在任何时候使指针无效,甚至在不知情的情况下覆盖内存中的部分代码......更不用说任何类型的偶尔异常(最有可能是访问冲突),但在我了解这件事的底部之前,我在某些项目中得到了和你一样的FPU废话(顺便说一句,你可以使用单fninit指示不时恢复FPU作为最后的手段)。

    有关更多信息以及如何解决它,请参阅:

于 2017-03-24T07:35:52.570 回答