深海小金鱼 发表于 2020-6-7 19:12:23

函数当作表达式时,为什么不能参与复合的赋值运算

#include<stdio.h>
#include<math.h>
int main()
{
    int t;
    unsigned long long intsum=0,weight;
    for(t=0;t<64;t++)
    {
      sum+=pow(2,t);
    }
    weight=sum/25000;
    printf("舍罕王应给予达依尔%llu粒麦子!\n",sum);
    printf("如果一公斤小麦有25000粒,舍罕王应给予达依尔%llu公斤麦子!\n",weight);
    return 0;
}
这个结果就不对!(原因在第九行那个pow()),请大神解释一下。万分感谢!

赚小钱 发表于 2020-6-7 19:20:57

我不清楚,为什么不把错误信息一起放出来,是在考验我们吗?

但是,一个明显的错误是,你的程序有溢出漏洞。

永恒的蓝色梦想 发表于 2020-6-7 19:44:28

赚小钱 发表于 2020-6-7 19:20
我不清楚,为什么不把错误信息一起放出来,是在考验我们吗?

但是,一个明显的错误是,你的程序有溢出漏 ...

很明显,这个数卡在了 unsigned long long 的边上,没溢出。

赚小钱 发表于 2020-6-7 20:15:10

pow -> powl

赚小钱 发表于 2020-6-7 20:18:53

本帖最后由 赚小钱 于 2020-6-7 20:20 编辑

永恒的蓝色梦想 发表于 2020-6-7 19:44
很明显,这个数卡在了 unsigned long long 的边上,没溢出。

pow 的返回值是 double,和 unsigned long long 运算就可能会出现精度问题。
这就是漏洞。

这也是我讨厌 c,python 的原因,不是强类型语言,不同类型之间竟然可以运算。

永恒的蓝色梦想 发表于 2020-6-7 20:22:35

赚小钱 发表于 2020-6-7 20:18
pow 的返回值是 double,和 unsigned long long 运算就可能会出现精度问题。
这就是漏洞。

好吧,我发现了,9223372036854775807 和 9223372036854775807.0 加法出现错误的结果。

永恒的蓝色梦想 发表于 2020-6-7 20:23:03

赚小钱 发表于 2020-6-7 20:15
pow -> powl

powl 的返回值是 long double,结果不会有任何差别。

赚小钱 发表于 2020-6-7 20:24:53

永恒的蓝色梦想 发表于 2020-6-7 20:22
好吧,我发现了,9223372036854775807 和 9223372036854775807.0 加法出现错误的结果。

      2251799813685247 +       2251799813685248 =       4503599627370495
      4503599627370495 +       4503599627370496 =       9007199254740991
      9007199254740991 +       9007199254740992 =      18014398509481983// 看这
   18014398509481984 +      18014398509481984 =      36028797018963968 // 事实上,在这里莫名其妙错了
   36028797018963968 +      36028797018963968 =      72057594037927936
   72057594037927936 +      72057594037927936 =   144115188075855872
    144115188075855872 +   144115188075855872 =   288230376151711744
    288230376151711744 +   288230376151711744 =   576460752303423488
    576460752303423488 +   576460752303423488 =    1152921504606846976
   1152921504606846976 +    1152921504606846976 =    2305843009213693952
   2305843009213693952 +    2305843009213693952 =    4611686018427387904
   4611686018427387904 +    4611686018427387904 =    9223372036854775808
   9223372036854775808 +    9223372036854775808 =                      0
舍罕王应给予达依尔0粒麦子!

int bar() {
    int t;
    unsigned long long sum = 0, weight;
    for (t = 0; t < 64; t++) {
      unsigned long long current = pow(2, t);
      printf("%22llu + %22llu = %22llu\n", sum, current, sum + current);
      sum += pow(2, t);
    }
    weight = sum / 25000;
    printf("舍罕王应给予达依尔%llu粒麦子!\n", sum);
    printf("如果一公斤小麦有25000粒,舍罕王应给予达依尔%llu公斤麦子!\n", weight);
    return 0;
}

永恒的蓝色梦想 发表于 2020-6-7 20:25:49

赚小钱 发表于 2020-6-7 20:18
pow 的返回值是 double,和 unsigned long long 运算就可能会出现精度问题。
这就是漏洞。



因为 Python 有 radd {:10_277:}

C 的类型转换也是一大槽点,各种奇葩操作{:10_247:}

赚小钱 发表于 2020-6-7 20:25:49

永恒的蓝色梦想 发表于 2020-6-7 20:23
powl 的返回值是 long double,结果不会有任何差别。

你试一下,it works on my machine.

永恒的蓝色梦想 发表于 2020-6-7 20:28:57

赚小钱 发表于 2020-6-7 20:25
你试一下,it works on my machine.

试了一下你 8L 的代码,在我这里,pow 和 powl 没出现区别。

深海小金鱼 发表于 2020-6-7 20:29:03

赚小钱 发表于 2020-6-7 19:20
我不清楚,为什么不把错误信息一起放出来,是在考验我们吗?

但是,一个明显的错误是,你的程序有溢出漏 ...

抱歉啊,本来是想贴图的(但我还不会贴图。。。)

赚小钱 发表于 2020-6-7 20:31:35

永恒的蓝色梦想 发表于 2020-6-7 20:28
试了一下你 8L 的代码,在我这里,pow 和 powl 没出现区别。

好吧,毕竟 c 不是跨平台的语言,我就没办法了。我的是 gcc 10.1.0

永恒的蓝色梦想 发表于 2020-6-7 20:35:17

赚小钱 发表于 2020-6-7 20:31
好吧,毕竟 c 不是跨平台的语言,我就没办法了。我的是 gcc 10.1.0

我是 Visual Studio 2019 。
页: [1]
查看完整版本: 函数当作表达式时,为什么不能参与复合的赋值运算