#c #visual-c #gcc #digits #numeric-limits
#c #visual-c #gcc #цифры #числовые ограничения
Вопрос:
У меня есть следующий код:
#include <iostream>
#include <limits>
int main()
{
std::cout << std::numeric_limits<unsigned long long>::digits10 << std::endl;
return 0;
}
- GCC 4.4 возвращает 19
- MS VS 9.0 возвращает 18
Может кто-нибудь, пожалуйста, объяснить, в чем разница между ними? Я бы ожидал, что такая константа будет одинаковой независимо от компилятора.
Комментарии:
1. У меня больше нет установки VC9, но печатается VC10
19
, что является ожидаемым значением, посколькуunsigned long long
представлено 64 битами, и, следовательно, его максимальное значение равно18,446,744,073,709,551,615
.2. @James, вот где я теряюсь: в есть 20
18,446,744,073,709,551,615
цифр, а не 19. Так почемуlimit10
возвращает 19 (или 18)?3. @Джеймс: msdn.microsoft.com/en-us/library/af6x78h6(v=vs.80).aspx Значит, в этой ситуации виноват msvc?
4. @Rikardo, может быть,
limit10
имеет смысл только для типов с плавающей запятой?5. @Frederic:
unsigned long long
может представлять9,999,999,999,999,999,999
(19 цифр), но не99,999,999,999,999,999,999
(20 цифр). Он может представлять каждое 19-значное число, но не каждое 20-значное число. [Извините, я прокомментировал ранее, но я понял, что это было не совсем правильно, поэтому я удалил этот комментарий.]
Ответ №1:
Если Visual C 2008 возвращает 18
for std::numeric_limits<unsigned long long>::digits10
, это ошибка (у меня не установлен Visual C 2008 для проверки описанного поведения).
В Visual C (по крайней мере, для 32-разрядной и 64-разрядной Windows) unsigned long long
является 64-разрядным целочисленным типом без знака и способен представлять все целые числа от нуля до 18 446 744 073 709 551 615 (264 — 1).
Следовательно, правильное значение для digits10
здесь равно 19, потому что unsigned long long
может представлять 9,999,999,999,999,999 (19 цифр), но не может представлять 99,999,999,999,999,999 (20 цифр). То есть он может представлять каждое 19-значное число, но не каждое 20-значное число.
При компиляции с Visual C 2010 ваша программа выводит ожидаемое значение 19.
Комментарии:
1. почему не 20 цифр? кажется, что в 19 отсутствует 1 цифра. как можно представить 18446744073709551615 19 цифрами?
2. @Rikardo:
unsigned long long
может представлять9,999,999,999,999,999,999
(19 цифр), но не99,999,999,999,999,999,999
(20 цифр). Он может представлять каждое 19-значное число, но не каждое 20-значное число.3. ооооооо. Я понимаю, так что это проблема минимального и превосходного значений. Спасибо!
Ответ №2:
numeric_limits::digits10 указывает количество десятичных разрядов слева от десятичной точки, которое может быть представлено без потери точности. Итак, я предполагаю, что это будет отличаться от компилятора к компилятору в зависимости от деталей их реализации.
Комментарии:
1. Вы только что процитировали документы msdn, вы НЕ предоставили ответа на вопрос, только добавили несвязанное предположение.
2. @Rikardo Koder: Ну, если это деталь реализации компилятора, она будет отличаться для каждого компилятора, и, как вы знаете, числа с плавающей запятой — это зло, вы никогда не можете быть уверены в том, какую точность вам предоставит каждый компилятор. Я думаю, что это предположение является достаточным аргументом для меня, чтобы рассматривать его как ответ.
3. беззнаковый long long — это целочисленный тип, а не тип с плавающей запятой.
Ответ №3:
В общем, утверждение
Я бы ожидал, что такая константа будет одинаковой независимо от компилятора.
это неверно, потому что размер типа в C не является фиксированным. Стандарт устанавливает только минимальное ограничение, и компиляторы могут свободно использовать более широкие типы. Например, некоторые странные компиляторы на 32 или 64-разрядном компьютере могут иметь CHAR_BIT = 9
и unsigned long long
больше не будут 64-разрядными, или они могут использовать другое дополнение 1 или некоторые другие кодировки чисел. Короче говоря, результат может отличаться у разных компиляторов.
Однако, если это unsigned long long
64-разрядный тип, то это определенно ошибка. Я только что проверил и увидел, что ошибка была исправлена в версии 2008. Возвращается правильное значение 19