【问题标题】:Rounding up decimals bug in c?c中的四舍五入错误?
【发布时间】:2019-12-07 15:02:37
【问题描述】:

我正在做一个非常简单的 c 程序,它接收整数 n 并找到 n 的平方根近似值。

这是我的平方根近似函数,直到小数点后 5 位:

float sqrt_approx(int n){
    float sqrt,how_many_tenths=10,how_many_decimals=0,i;
    for (i=1;i<n;i++){
        if ((i*i)<n) continue;
        if (i*i==n){ sqrt=i; goto return_; }
        else break;
    }
    sqrt=i-1;
    for (i=0;i<10;i++){
        if (i==9){

            sqrt=sqrt+i/how_many_tenths;

            how_many_tenths*=10;
            how_many_decimals++;
            if (how_many_decimals != 5) i=0;
            else break;
        }
        if ((sqrt+i/how_many_tenths)*(sqrt+i/how_many_tenths) < n) continue;
        sqrt=sqrt+(i-1)/how_many_tenths;
        how_many_tenths*=10;
        how_many_decimals++;
        if (how_many_decimals != 5) i=0;
        else break;
    }
    return_:
        return sqrt;
}

蛮力,我会说非常直观。但是,当我试图将近似值精确到小数点后 6 位时,就会出现问题。为了做到这一点,我需要做的就是改变这个:

if (how_many_decimals != 5)

进入:

if (how_many_decimals != 6)

两次都在我的代码中。如果我要计算 35 美元的平方根近似值到小数点后 6 位, 我得到 5.916080 美元而不是 5.916079 美元。

我试图找出错误,在我看来,小数点后第 5 位被四舍五入了。看一下,我只更改了一点代码来了解这里发生了什么:

float sqrt_approx(int n){
    float sqrt,how_many_tenths=10,how_many_decimals=0,i;
    for (i=1;i<n;i++){
        if ((i*i)<n) continue;
        if (i*i==n){ sqrt=i; goto return_; }
        else break;
    }
    sqrt=i-1;
    for (i=0;i<10;i++){
        if (i==9){
            printf("%f + %f equals: ",sqrt,i/how_many_tenths); //NEW
            sqrt=sqrt+i/how_many_tenths; //NEW
            printf("%f\n",sqrt); //NEW
            how_many_tenths*=10;
            how_many_decimals++;
            if (how_many_decimals != 6) i=0; //NEW (6 instead of 5)
            else break;
        }
        if ((sqrt+i/how_many_tenths)*(sqrt+i/how_many_tenths) < n) continue;
        sqrt=sqrt+(i-1)/how_many_tenths;
        how_many_tenths*=10;
        how_many_decimals++;
        if (how_many_decimals != 6) i=0; //NEW (6 instead of 5)
        else break;
    }
    return_:
        return sqrt;
}

结果(输入printf("%f,sqrt_approx(35)后):

$5.000000 + 0.900000$ 等于:$5.​​900000$(这很好)

$5.916070+0.000009$ 等于:$5.​​916080$(这不好)

$5.916080$

这里似乎有什么问题?

【问题讨论】:

  • 浮点值不够密集,无法获得超过 6 位小数的良好精度
  • 不要使用float;使用double。单精度浮点精度不足以使其可靠工作。
  • 修复了它。赞赏。
  • 35 的平方根是 5.91607978309961604256... 5.916080 是正确的近似值。 5.916079 完全错误
  • 35 的平方根不是 5.91607900000010001。如果您想近似 5.91607900000010001,请说出来,最好在一个单独的问题中使用尝试这样做的代码。

标签: c square-root


【解决方案1】:

将 float 更改为 double 修复了它。感谢你们的 cmets 伙计们。

【讨论】:

  • 永远不要使用“float”而不是“double”,除非你能很好地解释为什么使用float会更好。
  • @gnasher729 现在很有意义。
猜你喜欢
  • 1970-01-01
  • 2017-11-26
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 2012-08-04
  • 2023-03-26
相关资源
最近更新 更多