i=i+1 是未定义的行为吗?

Is i=i+1 an undefined behaviour?

我正在使用代码块,它为其他编译器提供了不同的输出,我找不到 it.What 这个程序中未定义行为的解决方案,是否有任何解决方案可以避免它?

这是在只有 3 和 4 的数字系统中打印第 n 个数字的代码。

#include<stdio.h>                                                              
#include<math.h>                                                               
int main(void)                                                                 
{                                                                              
    int n,i,value;                                                             
    scanf("%d",&n);                                                            
    value=i=0;                                                                 
    while(n>0)                                                                 
    {                                                                          
        if((n%2)==0)                                                           
        {                                                                      
            value+=4*pow(10,i);                                                
        }                                                                      
        else                                                                   
        {                                                                      
            value+=3*pow(10,i);                                                
        }                                                                      
        n=(n-1)/2;                                                             
        i=i+1;                                                                 
    }
printf("\nThe number is : %d",value);                                                                          
}

对于 6 以内的数字,它工作正常。大于 6 的数字的输出比实际应该的少 1。例如。如果 n=7,output=332 应该是 333.

编辑:提供带大括号的完整代码。

浮点数似乎被截断了。

您正在使用具有签名

的函数 pow()
double pow(double x, double y);

和计算作为 int。 Rounding/truncation 个错误?

此代码中没有未定义的行为。 i=i+1; 是明确定义的行为,不要与给出未定义行为的 i=i++; 混淆。

这里唯一可能导致不同输出的是 floating point inaccuracy

尝试 value += 4 * (int)nearbyint(pow(10,i)); 看看是否有任何不同。

这听起来像是一个编译器错误。 您将结果计算为 value+=3*pow(10,i); 但这实际上转化为 value+= (int)(3*pow(10,i));

这里有两件事中的一件可能是错误的:

  1. pow(10,0)!=1.0
  2. 转换为 int 错误地截断了结果。

要轻松调试它,只需尝试打印部分结果并查看问题所在。

这里的问题很可能是这个特定平台上的 pow 函数通过取参数的对数(可能是自然对数;可能是对数基数 2)乘以指数来执行计算,然后然后将第一个对数的底数提高到该乘积的幂。对无限精度数字执行这样的操作会产生数学上正确的结果,就像对扩展精度数字执行操作和 returning double 结果一样。我的猜测是,此实现中使用的 pow 函数可能是为一个平台编写的,该平台可以使用扩展精度数字执行中间计算,因此 return 可以更正双精度值,但它在缺少扩展精度类型的平台上 运行。因此,pow(10,3) 可能会 return 生成类似 999.9999999997 的内容,并将其强制转换为 int 会得到 999 而不是 1000。

如果您试图获得整数类型的结果,则确实没有理由将幂计算为浮点值。与其在循环中计算 10^i,不如让一个变量初始化为 1 并在每次循环中乘以 10 会更好。