【问题标题】:Inaccuracy when using pow() function使用 pow() 函数时不准确
【发布时间】:2016-03-26 18:32:02
【问题描述】:

我编写了一个程序,将一个数字拆分为多个数字,当它们相加时,给出第一个数字。例如,1234 应拆分为 1000、200、30 和 4。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

int main ()
{
int i, num1, num2;
char tmp[6];  // the number will be stored here as string
int num3 = 12345;  //the number 

sprintf(tmp, "%d", num3); //convert to string
for(i = 0; i < strlen(tmp); i++)  //check every digit
{
    num1 = pow(10, strlen(tmp) - 1 - i);  //every number will be multiplied by 10
                           //to the power of number of digits - 1 - counter
    num2 = tmp[i] - '0';   //convert character to int
    printf("%d\n", num1*num2); //print the number
}

 return 0;
}

这是输出:

9999
2000
297
40
5

如您所见,这是不正确的,为什么?

【问题讨论】:

  • 你发布的版本似乎和ideone.com/K3pY8r一样工作
  • 因为pow 包含一个浮点表示错误。
  • 我在多个在线编译器上尝试过,它确实有效,但它在我的 PC 上不起作用。如何避免该错误?
  • 如果需要精确值,请不要使用浮点数。
  • 那么为什么会出现这个错误,如何去掉浮点数呢?

标签: c numbers


【解决方案1】:

问题是浮点计算可能有小错误。也就是说pow函数的结果可能比预期的稍大或稍小。当您转换为 int 时,结果将被截断。例如,如果pow(10,4) 返回9999.999999,则转换为int 会产生9999,这与您的预期不同。另一方面,如果pow(10,3) 返回1000.000001,则转换为int 将得到预期的结果。

这里有一些代码可以演示问题(在pow 函数的结果不准确的计算机上):

int main( void )
{
    for ( int i = 0; i < 5; i++ )
    {
        double num1 = pow(10,i);
        int num2 = num1;
        printf( "%12f --> %5d\n", num1, num2 );
    }
}

为避免该问题,您要么需要对pow 的结果进行四舍五入,要么完全避免使用浮点数学运算。下面是一些代码,展示了如何仅使用整数数学来解决问题。

int main( void )
{
    char temp[] = "12345";
    int length = strlen( temp );

    int multiplier = 1;
    for ( int i = 1; i < length; i++ )
        multiplier *= 10;

    for ( int i = 0; i < length; i++ ) {
        printf( "%d\n", (temp[i] - '0') * multiplier );
        multiplier /= 10;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 2012-05-15
    • 2015-12-20
    • 2023-01-16
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    相关资源
    最近更新 更多