2013-12-05 2 views
2

Когда я компилирую мой кодC - Печать странно

#include <stdio.h> 

int main() { 
    int n, i, j; 
    float broj; 
    scanf("%d", &n); 
    for (i=0; i<=n; ++i) { 
     j=i; 
     broj = 0.1 * j; 
     while (j>=0) { 
      printf ("%3.1f ", broj-(j*0.1)); 
      j--; 
     } 
     printf(" %d. red\n", i); 
    } 
    return 0; 
} 

Это после того, как 5-й строки начинается печать первый номер, как -0.0 вместо 0.0, каждый 2-й ряд, так что его, как, что в 5-м, 7-й, 9-й и т.д. ..

+1

Для чего этот код? Что это значит? – DrakaSAN

+1

Можете ли вы также указать ввод и ожидаемый результат? –

+1

Кроме того, вы пробовали переходить через код в отладчике, построчно? Это может помочь вам понять, что происходит. –

ответ

4

Звучит как некоторые проблемы с точностью с плавающей точкой. Обратите внимание, что 0,1 не является точно представленным как float, поэтому каждый раз, когда вы его используете, вы будете использовать его приближение.

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

Хорошая рекомендация, как всегда What Every Computer Scientist Should Know About Floating-Point Arithmetic.

+0

Выглядит интересная тема! , что вы имеете в виду 0,1, не является точно представимым как float? – Srikanth

+0

@Srikanth См. Ссылку, которую я добавил, а также прочитал [этот раздел на странице Википедии о плавающей запятой] (http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding). – unwind

+0

@Srikanth: вам нужно прочитать: [Плавающая точка IEEE] (http://en.wikipedia.org/wiki/IEEE_754-1985) и [Дробное преобразование в двоичное преобразование] (http://cs.furman.edu/ digitaldomain/более/CH6/dec_frac_to_bin.htm). –

0

Используйте это в заявлении для печати:

printf ("%3.1f ", broj-(float)(j*0.1)); 
0

Слишком понимаю, что происходит вы можете сделаны небольшие изменения к вам программу. Согласно правилам продвижения по умолчанию аргументы от стандарта C printf() продвигает float до double. Таким образом, мы посмотрим на то, что происходит с числами в операциях в формате double (более дробная часть цифр):

 while (j>=0) { 
      printf ("%3.18lf ", j*0.1); 
      printf ("%3.18lf ", broj); 
      printf ("%3.18lf ", broj - j*0.1); 
      /*printf ("%3.18lf ", (double)(broj-(j*0.1)));*/ 
         break; 
      j--; 
     } 

Выход:

9 
0.000000000000000000 0.000000000000000000 0.000000000000000000 0. red 
0.100000000000000006 0.100000001490116119 0.000000001490116114 1. red 
0.200000000000000011 0.200000002980232239 0.000000002980232228 2. red 
0.300000000000000044 0.300000011920928955 0.000000011920928938 3. red 
0.400000000000000022 0.400000005960464478 0.000000005960464455 4. red 
0.500000000000000000 0.500000000000000000 -0.000000000000000028 5. red 
0.600000000000000089 0.600000023841857910 0.000000023841857877 6. red 
0.700000000000000067 0.699999988079071045 -0.000000011920928994 7. red 
0.800000000000000044 0.800000011920928955 0.000000011920928911 8. red 
0.900000000000000022 0.899999976158142090 -0.000000023841857960 9. red 

Выходные показывает эффекты, вызванные конечной точностью чисел. Таким образом, третий столбец должен состоять только из нулей, но из-за этого эффекта этого не происходит.

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