非黑莫白 发表于 2019-7-27 16:09:22

s1e6 问题

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

int main()
{
      long long int sum=0;
      long long int temp;
      long long int weight;
      int i;
      for (i=0;i<64;i++)
      {
                temp=pow(2,i);
                sum = sum + temp;
      }

      weight = sum / 25000;

      printf("%llu\n",sum);
      printf("%llu\n",weight);
      return 0;
}


没有warming,为什么最后weight返回的是0,sum就没有问题

jackz007 发表于 2019-7-27 16:34:38

本帖最后由 jackz007 于 2019-7-27 16:52 编辑

      楼主试试这个代码:

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

int main(void)
{
      double sum , temp , weight                              ;
      int i                                                   ;
      for (i = 0 , sum = 0.0 ; i < 64 ; i ++) sum += pow(2 , i) ;
      weight = sum / 25000                                    ;
      printf("%.0lf\n" , sum)                                 ;
      printf("%.0lf\n" , weight)                              ;
}

Neverturnback 发表于 2019-7-27 16:56:05

jackz007 发表于 2019-7-27 16:34
楼主试试这个代码:

取不到64的,i<64最高i = 63

jackz007 发表于 2019-7-27 17:48:31

本帖最后由 jackz007 于 2019-7-27 17:49 编辑

    问题似乎出在 pow(2 , i) 上
    下面的代码在我这里运行正常,TDM-GCC 5.1.0 x32 , 楼主也可以试试
#include <stdio.h>

int main()
{
      unsigned long longm , sum , temp , weight               ;
      int i , k                                                 ;
      for (i = 0 , sum = 0.0 ; i < 64 ; i ++) {
                for(k = 0 , m = 1 ; k < i ; k ++) m *= 2          ;
                sum += m                                          ;
      }
      weight = sum / 25000                                    ;
      printf("%I64u\n" , sum)                                 ;
      printf("%I64u\n" , weight)                              ;
}


      下面是运行实况:
C:\Bin>x1
18446744073709551615
737869762948382

Neverturnback 发表于 2019-7-27 18:08:47

jackz007 发表于 2019-7-27 16:34
楼主试试这个代码:

2的0次方 64位2进制表示就是 0000 ... 0001(0次方时这个1的位置是从右往左数第1个位置);
此时 sum = 0000 ... 0000 + 0000 ... 0001 = 0000 ... 0000;

2的1次方 64位2进制表示就是 0000 ... 0010(1次方时这个1的位置是从右往左数第2个位置);
此时 sum = 0000 ... 0001 + 0000 ... 0010 = 0000 ... 0011;


2的2次方 64位2进制表示就是 0000 ... 0100(2次方时这个1的位置是从右往左数第3个位置);
此时 sum = 0000 ... 0011 + 0000 ... 0100 = 0000 ... 0111;

.
.
.

2的63次方 64位2进制表示就是 1000 ... 0000(63次方时这个1的位置是从右往左数第64个位置);
此时 sum = 0111 ... 1111 + 1000 ... 0000 = 1111 ... 1111;

在long long int 中 1111 ... 1111 表示的值是 -1(这个去了解符数的2进制) ,-1 / 25000 = 0(所以weight的值是0)

printf中 %llu是以unsigned long long的方式打印所以 sum 1111 ... 1111 在long long中是-1, 在unsigned long long中就变成了2的64次方, weight本身就是0 从long long转换成 unsigned long long 还是0

(希望能对你有帮助)

Neverturnback 发表于 2019-7-27 18:09:51

Neverturnback 发表于 2019-7-27 18:08
2的0次方 64位2进制表示就是 0000 ... 0001(0次方时这个1的位置是从右往左数第1个位置);
此时 sum = 000 ...

第一个sum = 0000 ... 0000 + 0000 ... 0001 = 0000 ... 0001这边手误打错了 0-0

Neverturnback 发表于 2019-7-27 18:12:38

Neverturnback 发表于 2019-7-27 18:09
第一个sum = 0000 ... 0000 + 0000 ... 0001 = 0000 ... 0001这边手误打错了 0-0

下面的"符数" = "负数"!!!我的手残程度max0 -0

jackz007 发表于 2019-7-27 18:13:07

      long long int sum=0;
. . . . . .
      int i;
      for (i=0;i<64;i++)
      {
                temp=pow(2,i);
                sum = sum + temp;
      }

      这块代码折腾半天,其实就是为了得到一个 unsigned long long 所能表达的最大值 sum = 2 ^ 64 - 1 = 0xFFFFFFFFFFFFFFFF = 18446744073709551615,直接赋值就可以了。,

Neverturnback 发表于 2019-7-27 18:14:46

你把printf里面的%llu换成%lld就能很容易的找到问题的所在了

Neverturnback 发表于 2019-7-27 18:19:59

Neverturnback 发表于 2019-7-27 18:08
2的0次方 64位2进制表示就是 0000 ... 0001(0次方时这个1的位置是从右往左数第1个位置);
此时 sum = 000 ...

这里说错了 1111 ... 1111 是2的64次方 - 1 不是 2 的64次方qwq
页: [1]
查看完整版本: s1e6 问题