Почему некоторые цифры печатаются с десятичными знаками? - PullRequest
0 голосов
/ 15 сентября 2018

Я пытаюсь решить вопрос, который говорит:

Вы должны создать программу на C, которая показывает последовательность, как в примере ниже:

I=0 J=1
I=0 J=2
I=0 J=3
I=0.2 J=1.2
I=0.2 J=2.2
I=0.2 J=3.2
.....
I=2 J=?
I=2 J=?
I=2 J=?

Я пытался решить этот вопрос, используя структуру "for", но при выводе программы последние три целых числа появляются с десятичными знаками, и вопрос требует, чтобы целые числа появлялись без десятичных знаков:

I=0 J=1
I=0 J=2
I=0 J=3
I=0.2 J=1.2
I=0.2 J=2.2
I=0.2 J=3.2
.....
I=1 J=2
I=1 J=3
I=1 J=4
I=1.2 J=2.2
I=1.2 J=3.2
I=1.2 J=4.2
.....
I=2.0 J=3.0
I=2.0 J=4.0
I=2.0 J=5.0

Почему это происходит? Вот мой код:

int main() {

  int II;
  float I, J, X, FI;
  X = 1;

  for(I = 0; I <= 2.2; I = I + 0.2){

      for(J = X; J <= X + 2; J = J + 1){

          II = (int) I;     //II = The Integer part of I
          FI = I - II;      //FI = The Fractionary part of I

          if(FI == 0)
              printf("I=%.0f J=%.0f\n", I, J);

              //If the fractionary part is 0, then
              //the number must be printed without
              //decimal places.              

          else
              printf("I=%.1f J=%.1f\n", I, J);

              //If the fractionary part is greater than 0,
              //then the number must be printed with just
              //one decimal place.

      }

      X += 0.2;
  }

  return 0;
}

Ответы [ 4 ]

0 голосов
/ 16 сентября 2018

Почему некоторые числа печатаются с десятичными знаками?

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

Вместо этого были вычислены значения около цели ОП.


Ограничение проблем, вызванных попыткой выполнения десятичной математики с двоичными числами с плавающей точкой.

Поскольку код долженитерируйте 11 раз, используя I = [0, 0.2, 0.4, ... 2], используйте счетчик integer для цикла и создайте из него I.

// for (I = 0; I <= 2.2; I = I + 0.2) {
for (int i = 0; i <= 10; i++) {
  I = i/5.0;

Только с этим изменением вы получите

I=0 J=1
I=0 J=2
I=0 J=3
I=0.2 J=1.2
I=0.2 J=2.2
I=0.2 J=3.2
...
I=0.8 J=1.8
I=0.8 J=2.8
I=0.8 J=3.8
I=1 J=2
I=1 J=3
I=1 J=4
I=1.2 J=2.2
I=1.2 J=3.2
I=1.2 J=4.2
...
I=1.8 J=2.8
I=1.8 J=3.8
I=1.8 J=4.8
I=2 J=3
I=2 J=4
I=2 J=5

Чтобы понять, что пошло не так, полезно увидеть значения FP с гораздо большей точностью.Е. г .:

int main(void) {
  int II;
  float I, J, X, FI;
  X = 1;
  printf("0.2 (%.20f)\n", 0.2);
  printf("2.2 (%.20f)\n", 2.2);
  for(I = 0; I <= 2.2; I = I + 0.2){
      for(J = X; J <= X + 2; J = J + 1){
          II = (int) I;     //II = The Integer part of I
          FI = I - II;      //FI = The Fractionary part of I
          if(FI == 0)
              printf("I=%.0f J=%.0f (%.20f %.20f)\n", I, J, I,J);
          else
              printf("I=%.1f J=%.1f (%.20f %.20f)\n", I, J, I, J);
      }
      X += 0.2;
  }
}

Выход

0.2 (0.20000000000000001110)
2.2 (2.20000000000000017764)
I=0 J=1 (0.00000000000000000000 1.00000000000000000000)
I=0 J=2 (0.00000000000000000000 2.00000000000000000000)
I=0 J=3 (0.00000000000000000000 3.00000000000000000000)
I=0.2 J=1.2 (0.20000000298023223877 1.20000004768371582031)
I=0.2 J=2.2 (0.20000000298023223877 2.20000004768371582031)
I=0.2 J=3.2 (0.20000000298023223877 3.20000004768371582031)
I=0.4 J=1.4 (0.40000000596046447754 1.40000009536743164062)
I=0.4 J=2.4 (0.40000000596046447754 2.40000009536743164062)
I=0.4 J=3.4 (0.40000000596046447754 3.40000009536743164062)
I=0.6 J=1.6 (0.60000002384185791016 1.60000014305114746094)
I=0.6 J=2.6 (0.60000002384185791016 2.60000014305114746094)
I=0.6 J=3.6 (0.60000002384185791016 3.60000014305114746094)
I=0.8 J=1.8 (0.80000001192092895508 1.80000019073486328125)
I=0.8 J=2.8 (0.80000001192092895508 2.80000019073486328125)
I=0.8 J=3.8 (0.80000001192092895508 3.80000019073486328125)
I=1 J=2 (1.00000000000000000000 2.00000023841857910156)
I=1 J=3 (1.00000000000000000000 3.00000023841857910156)
I=1 J=4 (1.00000000000000000000 4.00000000000000000000)
I=1.2 J=2.2 (1.20000004768371582031 2.20000028610229492188)
I=1.2 J=3.2 (1.20000004768371582031 3.20000028610229492188)
I=1.2 J=4.2 (1.20000004768371582031 4.20000028610229492188)
I=1.4 J=2.4 (1.40000009536743164062 2.40000033378601074219)
I=1.4 J=3.4 (1.40000009536743164062 3.40000033378601074219)
I=1.4 J=4.4 (1.40000009536743164062 4.40000057220458984375)
I=1.6 J=2.6 (1.60000014305114746094 2.60000038146972656250)
I=1.6 J=3.6 (1.60000014305114746094 3.60000038146972656250)
I=1.6 J=4.6 (1.60000014305114746094 4.60000038146972656250)
I=1.8 J=2.8 (1.80000019073486328125 2.80000042915344238281)
I=1.8 J=3.8 (1.80000019073486328125 3.80000042915344238281)
I=1.8 J=4.8 (1.80000019073486328125 4.80000019073486328125)
I=2.0 J=3.0 (2.00000023841857910156 3.00000047683715820312)
I=2.0 J=4.0 (2.00000023841857910156 4.00000047683715820312)
I=2.0 J=5.0 (2.00000023841857910156 5.00000047683715820312)
0 голосов
/ 15 сентября 2018

Поскольку числа с плавающей точкой будут накапливать некоторую неточность во время итераций.Я сделал отладку вашего кода и в итерации значения FI = 1, точное значение было 8 конечных нулей.Но в итерации FI = 2 точное значение содержало некоторую ошибку, поэтому оно не входило в условие IF.Debug of code provided

0 голосов
/ 15 сентября 2018

Используйте% g.Как видно из этого поста

if (FI == 0) printf ("I =% g J =% g \ n", I, J);// используя% g

0 голосов
/ 15 сентября 2018

Числа с плавающей точкой не всегда точны, вам может потребоваться сделать что-то вроде:

if ((FI > -0.1) || (FI < 0.1))
   printf("I=%.0f J=%.0f\n", I, J);
else
   ...

OR

if (fabs(FI) < 0.1)
   printf("I=%.0f J=%.0f\n", I, J);
else
   ...

Обычная практика - не сравнивать поплавки / двойники по точности, но с небольшой разницей (эпсилон), которая зависит от конкретного применения.

В качестве примера из следующего кода C #:

float f = 1;

for (int i = 0; i < 10; i++)
{
  Console.WriteLine(f.ToString("G9"));
  f += 0.2F;
}

Это вывод; серия может быть не точной, если она хранится в формате с плавающей запятой:

1
1.20000005
1.4000001
1.60000014
1.80000019
2.00000024
2.20000029
2.40000033
2.60000038
2.80000043
...