2015-09-24 4 views
-1

Я пытался понять, как разные языки обрабатывают числа с плавающей запятой. Я знаю, что есть некоторые неотъемлемые вопросы в представление с плавающей запятой, поэтому, если вы делаете 0,3 + 0,6 в Python, вы получите 0.899999, а не 0,9Does printf() изменить свои параметры?

Однако эти фрагменты кода просто оставили меня изумлен:

double x = 0.1, 
    sum = 0; 

for(int i=0; i<10; ++i) 
    sum += x; 

printf("%.9lf\n",sum); 
assert(sum == 1.0); 

Вышеупомянутый фрагмент работает отлично. Он печатает 1.0. Однако, следующий фрагмент кода дает ошибку во время выполнения:

double x = 0.1, 
    sum = 0; 

for(int i=0; i<10; ++i) 
    sum += x; 

assert(sum == 1.0); 
printf("%.9lf\n",sum); 

Единственное изменение в двух фрагментах выше порядок и утверждают PRINTF заявления. Это заставляет меня думать, что printf каким-то образом модифицирует свои аргументы и как-то округляет их.

Может кто-нибудь, пожалуйста, проливает свет на это?

+0

Попробуйте ввести 16 цифр вместо 9. –

+8

Пожалуйста, никогда не обращайтесь за помощью к ошибке, которую вы получаете, не беспокоясь о том, какую ошибку вы получаете. Это безумие. –

+0

Это, похоже, еще один пример того, как не понимать, как работают числа с плавающей запятой. Бросьте на это недоразумение printf, и у вас есть беспорядок. – duffymo

ответ

6

Некоторые процессоры, такие как x86, имеют регистры с плавающей запятой, которые имеют более высокую точность, чем тип данных (80 бит, по сравнению с 64 бит для двойного). Вызов printf() заставляет эти регистры храниться в стеке, где для этой переменной выделено только 64 бита. Это вызывает разницу, которую вы наблюдаете.

Для получения дополнительной информации см What every computer scientist should know about floating-point arithmetic.

+0

Как «вызов print() заставляет эти регистры храниться в стеке?» * Они передаются в стек для 'printf()', но как это изменит исходную переменную 'sum'? –

+0

Без вызова функции printf() (или любой другой функции) возможно, что переменные хранятся в регистрах. Если thre является вызовом функции, переменные должны быть сохранены в стеке, потому что компилятор не может гарантировать, что вызываемая функция не будет использовать эти регистры для чего-то другого. –

+0

Я понимаю, о чем вы говорите. Интересно, если это то, что вызывает это. –

0

printf() не изменяет свои параметры.

Я не могу представить, как спросить об ошибке и не указывать, какую ошибку вы получаете. Вы имеете в виду, что это утверждает. Вы уверены, что оба не утверждают, но вы видите только тот, который по какой-то причине утверждает до printf()?

+0

Я не уверен, что понимаю ваш вопрос. Первый фрагмент кода не дает мне ошибки во время выполнения, но второй делает. Я не понимаю, почему это так. –

Смежные вопросы