Машинный максимум double на С++
Всем доброго вечера. У меня есть задача - определить максимально возможное значение, которое может храниться в типе double, но использовать библиотеку limits при решении нельзя. Решаю задачу с помощью возведения двойки в степень, при котором значение выходит за пределы типа. Нагляднее покажу в коде:
double infmax_d = 2.0;
double almostinf_d = 1.0, infinity_d = 1.0;
int counter_max_d = 0, counter_notmax_d = -1;
while (infmax_d > almostinf_d) {
almostinf_d = infmax_d;
infmax_d = infmax_d * 2.0;
counter_max_d++;
counter_notmax_d++;
}
//cout << counter_notmax_d << endl;
for (int t = 0; t < counter_notmax_d; t++) {
infinity_d = infinity_d * 2.0;
}
cout << "Max value for double type: " << infinity_d << endl;
Вывод программы в данном случае:
Max value for double type: 8.98847e+307
Это значение в два раза меньше истинного. При умножении на два сразу происходит вывод inf. Если отнять от infinity_d 0.5 и умножить на 2, результат тот же. Но если отнимать 5e300, то получается найти ближайшее к нужному число. Как можно модифицировать код, чтобы добиться нужного результата?
Ответы (1 шт):
Как уже заметил @gbg в комментарии, в соответствии со стандартом, единственный корректный способ узнать максимально возможное значение - причем не только типа double, но и любого арифметического типа - использовать ту самую библиотеку.
Можете открыть последний черновик N4868 последнего стандарта и найти там в § 6.8.2 описания для всех арифметических типов. В частности, в пункте 12 сообщается о числах с плавающей точкой.
- ... The value representation of floating-point types is implementation-defined. ... Specializations of the standard library template std::numeric_limits shall specify the maximum and minimum values of each arithmetic type for an implementation.
Если Вы хотите подробнее узнать, как устроены числа с плавающей точкой изнутри, то ссылку Вам дал @avp в комментарии. Если очень коротко, то число с плавающей точкой двойной точности может быть представлено 64 битами, при этом
- 0 бит = знак числа
- 1 - 11 биты = смещенный порядок
- 12 - 63 биты = абсолютная часть мантиссы
Я воспользовался библиотекой limits, чтобы получить максимальное double , а затем посмотрел, как оно представлено в памяти.
double d = numeric_limits<double>::max( ); // 1.79769e+308
// 0 11111111110 11...11 // представление в памяти
// ^ ^ ^ ^ ^
// 0 1 11 12 63
Со знаковым битом все понятно, если бы там была единица, мы бы получили отрицательное число. Но, как видите, и 11ый бит тоже выставлен в 0. Значит, прямолинейное выставление всех битов в единички не сработает. Если Вы все же попробуете, то вывод, скорее всего, окажется nan то есть "not a number".
Поэтому, когда преподаватель скажет Вам правильный способ, вернитесь, пожалуйста, сюда и явите это решение свету. Очень любопытно его очень-очень-очень железобетонное обоснование