liyibo373 发表于 2019-6-4 10:53:53

C语言中,鱼C第一季第六课的动动手1为什么我计算的结果是0

以下是我的代码:
#include <stdio.h>
#include <math.h>
main()
{
      int i;
      
      unsigned long long sum = 0;
               
      for ( i = 0; i < 64; i++ ){
               
                sum = sum + pow(2, i);
      }
      
      printf( "舍罕王应该给予达依尔%llu粒麦子。\n", sum );
      printf( "如果每25000粒麦子为1kg,那么应该给%llukg麦子", sum / 25000 );
      
      return 0;
}

结果计算出来是:舍罕王应该给予达依尔0粒麦子。如果每25000粒麦子为1kg,那么应该给0kg麦子


mqcake 发表于 2019-6-4 11:03:59

我跑了一下,不等于0

猫也想敲代码 发表于 2019-6-4 11:16:08

舍罕王应该给予达依尔18446744073709551615粒麦子。
如果每25000粒麦子为1kg,那么应该给737869762948382kg麦子

jackz007 发表于 2019-6-4 11:26:35

      楼主可以把 printf() 中的 "%llu" 替换为 "%I64u" 试试看呢。

liyibo373 发表于 2019-6-4 13:33:44

猫也想敲代码 发表于 2019-6-4 11:16
舍罕王应该给予达依尔18446744073709551615粒麦子。
如果每25000粒麦子为1kg,那么应该给737869762948382k ...

我的执行结果真是0,不知道为什么

liyibo373 发表于 2019-6-4 13:48:13

jackz007 发表于 2019-6-4 11:26
楼主可以把 printf() 中的 "%llu" 替换为 "%I64u" 试试看呢。

换成%I64u也是0,我的是win7系统,安装了dev-C++

Croper 发表于 2019-6-4 14:49:03

本帖最后由 Croper 于 2019-6-4 14:52 编辑

#include <stdio.h>
#include <math.h>
main()
{
      int i;
      
      unsigned long long sum = 0;
               
      for ( i = 0; i < 64; i++ ){
               
                sum = sum + (unsigned long long)pow(2, i);//这里加一个unsigned long long
      }
      
      printf( "舍罕王应该给予达依尔%llu粒麦子。\n", sum );
      printf( "如果每25000粒麦子为1kg,那么应该给%llukg麦子", sum / 25000 );
      
      return 0;
}

等于0的原因是因为这道题的答案是2^64-1,刚好是unsigned long long的上界
而pow函数的返回值是double类型,那么运行时,等式右边的结果也是double类型,自动转换为unsigned long long,再赋值给sum,
但是double类型的分数位只有52位,换句话说,其精度大概只有16到17位,其并不能精确地表示2^64-1,换算后,可能近似为2^64,那么对于unsigned long long就直接溢出为0了

处理方法就是先把pow的结果转换为unsigned long long(double对于其表示范围内的2的整数次方总是能精确表示的),再行计算,就不存在近似的问题了
页: [1]
查看完整版本: C语言中,鱼C第一季第六课的动动手1为什么我计算的结果是0