0

每当我输入 65 岁或以下的年龄时,我会得到一个小于 2,100,000 的数字。但是,当我输入 68 岁或更高的年龄时,结果会立即变为 18,446,744,071,590,568,320,这是 uint64_t 的最大值。我不知道为什么结果会出现这种跳跃。它一直运行良好,直到大约 2,100,000。

// How many seconds have I lived?
#include <stdio.h>
#include <string>
#include <cstdint>
using namespace std;
string addCommas(uint64_t answer);
int main ()
{
    int seconds = 60, minutes = 60, hours = 24, days = 365;
    int years; uint64_t secondsLived, secondsAwake;
    printf("How many years have you lived? ");
    scanf("%d",&years);
    secondsLived = seconds*minutes*hours*days*years;
    secondsAwake = (float)secondsLived*0.666;

    printf("\nYou have existed for %s seconds\n",addCommas(secondsLived).c_str());
    printf("You have been awake for %s seconds\n",addCommas(secondsAwake).c_str());
}
string addCommas(uint64_t answer){
    string num = to_string(answer);
    int insertplace = (int)num.length() - 3;
    while (insertplace > 0) {
        num.insert(insertplace, ",");
        insertplace-=3;
    }
    return num;
}

这里有几个输出:

How many years have you lived? 67

You have existed for 2,112,912,000 seconds
You have been awake for 1,407,199,392 seconds


How many years have you lived? 69

You have existed for 18,446,744,071,590,568,320 seconds
You have been awake for 12,285,531,553,090,562,048 seconds
4

3 回答 3

4

在这一行:

secondsLived = seconds*minutes*hours*days*years;

您将多个ints 相乘,然后将结果分配给uint_64. s上的计算int溢出。

uint_64在将它们相乘之前将至少一个值转换为,以便对uint_64值进行计算:

secondsLived = (uint_64)seconds*minutes*hours*days*years;
于 2014-06-12T21:27:05.730 回答
3
secondsLived = seconds*minutes*hours*days*years;

您将结果分配给 a 的事实uint64_t对它的计算方式没有影响。

于 2014-06-12T21:25:08.850 回答
2

因为seconds, minutes, hours, days, 和years都是有符号整数,所以整个计算都是在有符号整数中完成的。当您输入大量年份时,它会溢出int。当溢出的结果转换为无符号 64 位整数时,由于负数在二进制补码系统中的表示方式,您会得到一个非常大的数字。

声明任何单位变量(比如years) auint64_t可以解决这个问题:

int seconds = 60, minutes = 60, hours = 24, days = 365;
uint64_t years, secondsLived, secondsAwake;
于 2014-06-12T21:27:41.453 回答