Явная спецификация представления двойной точности, используемого компилятором - PullRequest
0 голосов
/ 19 ноября 2018

Недавно я столкнулся с проблемой, что visual-c++ не соответствует IEEE 754 , но вместо этого использует субнормальное представление . То есть значения с плавающей запятой двойной точности не имеют обычного представления 1 знакового бита, 11 экспоненциальных битов и 52 явно хранимых значащих десятичных битов, см. Ниже.

Поскольку gcc и clang, однако, являются совместимыми, а согласованное кроссплатформенное поведение крайне желательно, я хотел бы знать, возможно ли заставить visual-c++ использовать нормальное представление. Альтернативно, использование gcc и clang использования субнормального представления, конечно, также решит проблему.

Проблема различных двойных представлений может быть воспроизведена в visual-c++, gcc и clang с использованием следующего кода:

#include <iostream>
#include <string>

int main()
{
    try {
        std::stod("8.0975711886543594e-324");
        std::cout << "Subnormal representation.";
    } catch (std::exception& e) {
        std::cout << "Normal representation.";
    }
    return 0;
}

Возможна ли спецификация представления для создания согласованного поведения во всех трех случаях?

Редактировать: Как указывало geza , это возникает проблема в различных реализациях std::stod, которые затем задали бы вопрос, если есть любой способ заставить std::stod вести себя согласованно, без необходимости использовать отдельную оболочку для него.

1 Ответ

0 голосов
/ 19 ноября 2018

К сожалению, std::stod плохо спроектирован, потому что невозможно определить причину исключения std::out_of_range.

Я бы предложил вам использовать strtod вместо этого.Хотя в стандарте не указано, что эта функция должна делать для субнормальных чисел, она обычно ведет себя хорошо для субнормальных чисел (это означает, что она возвращает субнормальные числа).Преимущество этой функции в том, что она возвращает значимый результат для ситуаций вне диапазона, поэтому можно определить причину выхода за пределы диапазона.

Если вы хотите обработать ситуации вне диапазонаВам нужно будет проверить errno на ERANGE.Обратите внимание, что если результатом является субнормальное / нулевое число, то, возможно, errno будет установлено на ERANGE, что следует игнорировать (вы можете проверить это с помощью fpclassify).

Так чтологика примерно такая:

double r = strtod(string, &end);
// here, check for end to know about invalid strings

if (errno==ERANGE) { // out-of-range (overflow, underflow)
    int c = fpclassify(r);
    if (c!=FP_SUBNORMAL&&c!=FP_ZERO) { // let's filter out underflow cases
        // "real" out of range handling here, just overflow
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...