为什么有些数字印有小数位?

问题描述 投票:-1回答:4

我正在尝试解决一个问题:

您必须在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;
}
c for-loop floating-point formatting
4个回答
2
投票

浮点数并不总是准确的,您可能需要执行以下操作:

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

要么

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

1
投票

为什么有些数字印有小数位?

因为所采用的算法假设精确的十进制浮点数学,但使用公共二进制浮点double

相反,计算了OP目标附近的值。


限制因尝试使用二进制编码的浮点数进行十进制数学运算而导致的问题。

由于代码需要使用I = [0, 0.2, 0.4, ... 2]迭代11次,因此使用循环的整数计数器并从中构造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值更精确地看待是有用的。 E. g。:

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
投票

因为浮点数会在迭代期间累积一些不精确度。我已经完成了代码的调试,并且在值FI = 1的迭代中,确切的值是8个尾随零。但是在FI = 2的迭代中,确切的值有一些误差,因此它不会进入IF条件。 Debug of code provided


0
投票

使用%g。正如this post所见

if(FI == 0)printf(“I =%g J =%g \ n”,I,J); //使用%g

© www.soinside.com 2019 - 2024. All rights reserved.