【问题标题】:Why is "int" not working correctly with "j" but long long is working fine?为什么“int”不能与“j”一起正常工作,但 long long 工作正常?
【发布时间】:2020-09-01 03:59:41
【问题描述】:

这是我的代码int j:

void solve(){
    unsigned long long n;
    cin>>n;
    unsigned long long sum = 0;
    int j = 1;
    for(int i=3;i<n+1;i+=2){
        sum += ((4*i)-4)*(j);
        j++;
    }
    cout<<sum<<"\n";
    }
Input:
499993

Output:
6229295798864

但它给出了错误的输出,这是我的代码 long long j 工作正常:

void solve(){
    int n;
    cin>>n;
    unsigned long long sum = 0;
    long long j = 1;
    for(int i=3;i<n+1;i+=2){
        sum += ((4*i)-4)*(j);
        j++;
    }
    cout<<sum<<"\n";
    }
Input:
499993

Output:
41664916690999888

在这种情况下,j 的值远低于499993,它在int 范围内,但仍然无法正常工作。为什么会发生这种情况?

这里是实际problem 的链接。以防万一,你想看看。

【问题讨论】:

  • 大概((4*i)-4)*(j) 产生的东西比int 可以容纳的更大
  • 更重要的是,直到实际赋值(由于unsigned long long 与int 的等级),表达式才被提升为unsigned long long。评估期间的所有操作数都保留为int,结果(溢出)也是如此。您会发现,如果您更改了 i 而不是 j,它同样会正确解析。
  • 您似乎认为表达式不再“适合”给定类型时会自我提升。这不是语言的工作方式。隐式提升发生在操作数级别,在您的情况下,直到赋值才会发生。顺便说一句,您还可以将前导 4 切换到 4ULL (我想我是对的;我很少使用 UL 之外的文字常量),它也应该可以工作,留下 i 和 j 原样。关键是强制将该表达式提升到unsigned long long在分配之前。
  • long long 的意义在于能够存储更大的整数值。这与整数表达式中的所有操作数都是纯 ints 的事实完全无关。只要他们还在,操作就会在ints 上完成。事实上,你的程序中有一些其他变量是 long long int,或者甚至表达式的结果将被分配给它,这一事实是无关紧要的,并且不会改变所有操作数都是 ints 的事实,所以所有表达式将被如此评估。
  • 顺便说一下,这通常是您应该避免使用无符号整数类型的情况。如果你的总和溢出,它可能会被忽视,因为它会简单地扭曲,产生一个不正确但看似可以接受的答案。

标签: c++ int overflow long-integer long-long


【解决方案1】:

注意((4*i)-4)*(j) 的结果是一个int,因为i 和j 都是int 类型。仅当将 ((4*i)-4)*(j) 添加到 sum 时,右侧才会提升为 unsigned long long。但是表达式 ((4*i)-4)*(j) 在被提升之前已经溢出了 int 类型的大小以达到足够大的 n。

但是,如果您将 i 或 j 更改为 unsigned long long,则表达式 ((4*i)-4)*(j) 将被评估为 unsigned long long,安全地在大小限制内。

【讨论】:

  • 不只是i 和j 是int 类型; 4 也是。将表达式更改为(4ULL * i - 4) * j(是的,我已经删除了(冗余(混淆))括号)也可以。我对这里的三种方法中的哪一种最好没有意见。 +1。
【解决方案2】:

在表达式的第一个代码sn-p中

((4*i)-4)*(j)

赋值语句

sum += ((4*i)-4)*(j);

(4*i)-4) 和 (j) 两个操作数的类型均为 int。所以表达式的类型(操作数的常用类型)也是int。但是int 类型的对象不足以存储结果值。所以这里发生了溢出。

当j 被声明为具有long long 类型时

long long j = 1;

那么上面表达式的常见类型也是long long。这意味着由于通常的算术转换,此操作数(4*i)-4) 也被转换为类型long long。并且这种类型的对象可以存储为输入数据提供的结果值。

您可以检查int 和long long 类型的对象中可以存储的最大值是多少。

你来了。

#include <iostream>
#include <limits>

int main() 
{
    std::cout << "The maximum value of an object of the type int is "
              << std::numeric_limits<int>::max()
              << '\n';

    std::cout << "The maximum value of an object of the type long long is "
              << std::numeric_limits<long long>::max()
              << '\n';

    return 0;
}

程序输出可能看起来像

The maximum value of an object of the type int is 2147483647
The maximum value of an object of the type long long is 9223372036854775807

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2021-12-06
    • 2011-08-29
    • 2021-12-15
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多