Исключение с плавающей запятой для типа double -> unsigned __int64 в C++ Builder 10.1

В C++ Builder 10.1 Berlin возникает проблема с определенными типами типов с двойным и без знака __int64 в Берлине, вызывающими исключение недопустимой операции с плавающей запятой ($C0000090).

Мое приложение позволяет вводить данные пользователем, поэтому мне нужно иметь возможность обрабатывать любые значения, но для простоты, давайте использовать следующий пример:

double dValue = 9223372036854775807.0;
unsigned __int64 uhValue = (unsigned __int64) dValue;

Хотя я могу обработать это исключение при попытке / перехвате, это, похоже, повредит стек регистров FPU, и последующие операции с плавающей запятой сгенерируют исключение проверки стека с плавающей запятой.

В следующем отчете о проблеме описана похожая проблема, и на ней есть потенциальное решение: http://qc.embarcadero.com/wc/qcmain.aspx/qcmain.aspx?d=119745

Я хотел бы предотвратить первоначальное исключение с плавающей запятой, если это вообще возможно. Помимо потери точности, значение, хранящееся в double, находится в допустимом диапазоне без знака __int64, поэтому у меня возникают проблемы с пониманием того, что вызывает исключение.

Есть ли что-то, что я мог бы сделать по-другому, когда дело доходит до обработки / преобразования типов или обработки исключений?

Как примечание, фрагмент кода выше отлично работает в Visual Studio и устанавливает для uhValue значение 9223372036854775808.

Спасибо!

1 ответ

Решение

Я использую только старый 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() не был должным образом сбалансирован.

    Отсутствует glEnd() выкидывал исключения стека FPU все время в несвязанном коде к этому...

  2. BCB6 унаследовал ошибку движка и компилятора Borland C++.

    Я не использую BCB6 (я на BDS2006), но вы, ребята, подтвердили, что он также присутствует (BCB5 был в порядке) и, возможно, также в более новых версиях Borland. Просто конструктор по умолчанию, сгенерированный компилятором, содержит ошибки, приводящие к хаосу в компиляторе и движке C++. В сочетании с ошибкой диспетчера памяти (двойное удаление указателя не выдает исключение, а делает недействительным диспетчер памяти), вы можете в любое время лишить законной силы указатели, не зная, что они перезаписывают даже части кода в памяти... не говоря уже о случайных исключениях любого вида (наиболее вероятных) является нарушением прав доступа), но я получил то же дерьмо FPU, что и вы, для некоторых проектов, прежде чем я получил в конце этой вещи (кстати, вы можете использовать один fninit Инструкция по восстановлению ФПУ время от времени в крайнем случае).

    Для получения дополнительной информации и как ее решить см.:

Другие вопросы по тегам