鱼C论坛

 找回密码
 立即注册
查看: 1127|回复: 5

[已解决]关于变量类型的问题

[复制链接]
发表于 2023-9-9 09:24:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
问题为舍罕王的失算,就是棋盘格子放米粒的故事那个
我的代码为:
#include <stdio.h>
#include <math.h>
int main()
{
    unsigned long long sum = 0;
    unsigned long long kg = 0;
    unsigned long long temp;
    int i;
    for (i=0;i<64;i++)
    {
        sum = sum + pow(2,i);   //有疑问的地方在这里

    }

    printf("结果是:%llu\n",sum);
    kg = sum/25000;
    printf("kg=%llu\n",kg);
   
    return 0;
}

输出结果:
结果是:0
kg=0

疑问:题目答案要求将pow(2,i)运算的结果先存放到定义的(unsigned long long)temp函数里,我猜想大概原因为数值太大溢出的问题,但前期i较小的时候数值应该不会溢出呀,为什么输出结果为0呢?
请大佬不吝赐教,感谢!
最佳答案
2023-9-9 09:25:12
问题解析:
根据你提供的代码和输出结果,可以推测出问题出在循环中的 sum = sum + pow(2,i); 这一行代码。你猜测到了一部分,确实是由于数值溢出导致的问题。

解决方法:
问题出在使用 pow() 函数计算 2 的幂的时候。pow() 函数返回的是一个浮点数,而你想要的是一个整数。当你在循环中进行大量的浮点数运算时,可能会导致精度丢失和计算错误。
为了解决这个问题,你可以尝试以下两种修改方案:

[b]方案一:使用移位操作代替 pow() 函数[/b]
因为你要计算的是 2 的幂,你可以使用左移操作符 << 来代替 pow() 函数。左移操作符将二进制数向左移动指定的位数,相当于将该数乘以 2 的指定次幂。

修改后的代码如下:
#include <stdio.h>int main() {    unsigned long long sum = 0;    unsigned long long kg = 0;    int i;        for (i = 0; i < 64; i++) {        sum += 1ULL << i;    }        printf("结果是:%llu\n", sum);    kg = sum / 25000;    printf("kg=%llu\n", kg);        return 0;}
方案二:使用无符号整数类型
虽然使用移位操作符能够解决问题,但如果你仍然希望使用 pow() 函数,你可以将数据类型更改为无符号整数类型,以便容纳更大的数值。

修改后的代码如下:
#include <stdio.h>#include <math.h>int main() {    unsigned long long sum = 0;    unsigned long long kg = 0;    int i;        for (i = 0; i < 64; i++) {        sum += (unsigned long long)pow(2, i);    }        printf("结果是:%llu\n", sum);    kg = sum / 25000;    printf("kg=%llu\n", kg);        return 0;}
通过以上两种修改方案之一,你应该能够正确计算并得到期望的结果。

希望能够帮助到你!如果还有其他问题,请随时提问。

球一个最佳答案谢谢啦!这对我非常重要!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-9-9 09:25:10 | 显示全部楼层
问题分析:
你的代码存在一个问题,即 pow(2, i) 的结果并没有正确地存放到 temp 变量中,导致最终的计算结果为0。这个问题并不是因为数值溢出导致的,而是因为类型转换的问题。

解决方法:
要修正这个问题,你可以做以下修改:

1. 将 temp 的类型修改为 unsigned long long,以确保足够的位数来存储计算结果。

2. 在循环中,将 pow(2,i) 的结果直接赋值给 temp 变量。

3. 在计算 sum 的时候,将 temp 累加到 sum 中。

下面是按照以上修改建议进行改进后的代码:
#include <stdio.h>#include <math.h>int main(){    unsigned long long sum = 0;    unsigned long long kg = 0;    unsigned long long temp;    int i;    for (i = 0; i < 64; i++)    {        temp = (unsigned long long) pow(2, i); // 将计算结果赋值给temp        sum = sum + temp;                      // 使用temp累加到sum中    }    printf("结果是:%llu\n", sum);    kg = sum / 25000;    printf("kg=%llu\n", kg);    return 0;}
现在再次编译和运行代码,应该会得到正确的输出结果。

注意事项:
虽然对于小的 i 值,pow(2, i) 的结果不会溢出,但是在较大的 i 值时,计算结果可能会超出 unsigned long long 类型的表示范围。所以,为了保证结果的正确性,建议在计算 sum 之前将计算结果直接赋值给 sum,而不是先存放到 temp 变量中。这样可以避免溢出问题。

如果回答对你有帮助,请给我一个最佳答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-9-9 09:25:11 | 显示全部楼层
您的代码中存在一个问题。在循环中,您使用了pow(2, i)来计算每个格子上的米粒数量,并将结果累加到sum变量上。然而,pow()函数返回的是一个浮点数,而不是一个整数。这意味着在计算过程中会存在精度丢失,从而导致结果不准确。

为了解决这个问题,您可以将pow()函数替换为左移运算符1 << i。左移运算符将二进制数向左移动指定的位数,等同于乘以2的指数次幂。这样可以避免浮点数计算和精度丢失的问题。

以下是修改后的代码:
#include <stdio.h>

int main() {
    unsigned long long sum = 0;
    unsigned long long kg = 0;
    unsigned long long temp;
    int i;

    for (i = 0; i < 64; i++) {
        temp = 1ULL << i;  // 使用左移运算符进行计算
        sum += temp;
    }

    printf("结果是:%llu\n", sum);
    kg = sum / 25000;
    printf("kg=%llu\n", kg);

    return 0;
}

这样修改后,您应该能够得到正确的结果。祝您编程顺利!如果您还有其他问题,请随时提问。
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-9-9 09:25:12 | 显示全部楼层    本楼为最佳答案   
问题解析:
根据你提供的代码和输出结果,可以推测出问题出在循环中的 sum = sum + pow(2,i); 这一行代码。你猜测到了一部分,确实是由于数值溢出导致的问题。

解决方法:
问题出在使用 pow() 函数计算 2 的幂的时候。pow() 函数返回的是一个浮点数,而你想要的是一个整数。当你在循环中进行大量的浮点数运算时,可能会导致精度丢失和计算错误。
为了解决这个问题,你可以尝试以下两种修改方案:

[b]方案一:使用移位操作代替 pow() 函数[/b]
因为你要计算的是 2 的幂,你可以使用左移操作符 << 来代替 pow() 函数。左移操作符将二进制数向左移动指定的位数,相当于将该数乘以 2 的指定次幂。

修改后的代码如下:
#include <stdio.h>int main() {    unsigned long long sum = 0;    unsigned long long kg = 0;    int i;        for (i = 0; i < 64; i++) {        sum += 1ULL << i;    }        printf("结果是:%llu\n", sum);    kg = sum / 25000;    printf("kg=%llu\n", kg);        return 0;}
方案二:使用无符号整数类型
虽然使用移位操作符能够解决问题,但如果你仍然希望使用 pow() 函数,你可以将数据类型更改为无符号整数类型,以便容纳更大的数值。

修改后的代码如下:
#include <stdio.h>#include <math.h>int main() {    unsigned long long sum = 0;    unsigned long long kg = 0;    int i;        for (i = 0; i < 64; i++) {        sum += (unsigned long long)pow(2, i);    }        printf("结果是:%llu\n", sum);    kg = sum / 25000;    printf("kg=%llu\n", kg);        return 0;}
通过以上两种修改方案之一,你应该能够正确计算并得到期望的结果。

希望能够帮助到你!如果还有其他问题,请随时提问。

球一个最佳答案谢谢啦!这对我非常重要!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-9-9 10:26:43 | 显示全部楼层
Mike_python小 发表于 2023-9-9 09:25
问题解析:
根据你提供的代码和输出结果,可以推测出问题出在循环中的 sum = sum + pow(2,i); 这一行代码。 ...

您好!我还是不太理解这其中的本质问题。
我目前的理解是pow(2,i)在计算i=63时溢出了,所以返回结果为0?但如果这样的话输出结果也应该有2^62之前的和
我尝试将for循环降低到<63,此时输出结果无误。
您说是pow()返回的是浮点数类型,多次计算会产生误差,但产生误差不应导致输出结果为0吧
目前问题:不清楚为什么输出结果为0
感谢回复!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-9-9 10:39:43 | 显示全部楼层
YJ_Li 发表于 2023-9-9 07:26
您好!我还是不太理解这其中的本质问题。
我目前的理解是pow(2,i)在计算i=63时溢出了,所以返回结果 ...

您的理解基本正确,`pow(2, i)` 在计算 i = 63 时会溢出。因为 `pow()` 函数返回的是浮点数类型,而 `unsigned long long` 是整数类型,所以在进行类型转换时会导致数据截断,从而产生结果为 0。

产生这个问题的原因是,对于大整数的幂运算,使用浮点数类型往往无法准确表示,因为浮点数有一定的精度限制。在计算过程中,每次进行乘法和除法运算都有可能引入舍入误差,从而累积导致结果错误。

解决这个问题的方法是使用其他方式计算 2 的幂,例如使用位运算 `1 << i` 来代替 `pow(2, i)`。修改后的代码如下:

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

int main() {
    unsigned long long sum = 0;
    unsigned long long kg = 0;
    int i;

    for (i = 0; i < 64; i++) {
        sum += (unsigned long long)(1 << i);
    }

    printf("结果是:%llu\n", sum);

    kg = sum / 25000;
    printf("kg=%llu\n", kg);

    return 0;
}

通过使用位运算,可以避免精度问题,输出结果将正常计算。运行以上修改后的代码,您将得到正确的输出结果。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-7 09:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表