【问题标题】:I have to find the maximum sum of 4 numbers from an array of 5. My code fails for bigger numbers我必须从 5 个数组中找到 4 个数字的最大总和。我的代码因更大的数字而失败
【发布时间】:2020-01-15 05:44:59
【问题描述】:

我必须从 5 个数组中找到 4 个数字的最大和,并以相同的方式找到最小和。我的代码在一些较大的测试用例中失败,因为由于某种原因最大值变为负数

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int minimini(int list[]){
    int minisum=0;
    int taker;
    int a=max({list[0],list[1],list[2],list[3],list[4]});
    for (int i=0; i<5; i++){
        taker=list[i];
        if(taker!=a){
            minisum=minisum+taker;
        }
    }
return minisum;
}
int maxa(int list[]){
    int maxsum=0;
    int taker;
    int a=min({list[0],list[1],list[2],list[3],list[4]});
    for (int i=0; i<5; i++){
        taker=list[i];
        if(taker!=a){
            maxsum=maxsum+taker;
            cout<<"maxsum >>"<<maxsum;
            cout<<"a="<<a;
        }
    }
return maxsum;
}
int main(){
    int list[5];
    int minisum, maxsum;
    for (int i=0; i<5; i++){
        cin>>list[i];
    }

    minisum=minimini(list);
    maxsum=maxa(list);

    cout<<minisum<<" "<<maxsum;


    return 0;
}

【问题讨论】:

  • 有没有想过当列表中有多个最小/最大元素副本时会发生什么?
  • 您可以对 5 的数组进行排序(例如,使用 std::sort)。那么最小和是前4个元素的和,最大和是后4个元素的和,不是吗?
  • 我的代码在一些较大的测试用例中失败:这可能是溢出问题吗?你能提供失败的示例输入吗?
  • 输入是否有限制范围? (考虑一下当所有数字都是INT_MAX / 2 时会发生什么。)
  • @Scheff 输入 -> 256741038、623958417、467905213、714532089、938071625

标签: c++


【解决方案1】:

您的代码受到Integer Overflow 的影响。大多数现代计算机中的整数范围从-2,147,483,6482,147,483,647。由于您在 cmets 中提到您的输入可以从 1 变为 10^9 并且数组的大小为 5,因此最大和可以是 5 * 10^9 ,这确实大于 2,147,483,647。您只需要一个可以容纳更大值的数据类型,使用:

  1. long long
  2. std::int64_t

请注意,即使 unsigned int 也无法完成这项工作,因为它是 4,294,967,295 5 * 10^9。另一件事是之间的区别

A. int a = 2,147,483,647 ; int b = 2,147,483,647 ; long long k = a + b 。现在,由于 ab 是整数,因此在将其分配回 long long 之前会发生溢出,因为会发生整数加法,也就是 32 bit 加法。

B. long long a = 2,147,483,647; long long b = 2,147,483,647; long long k = a + b。现在,溢出不会发生,因为加法将在 long long 上执行,因为 a 和 b 是 long long64 bit 加法会发生

代码如下所示:

long long list[5]; //See int is now long long
long long minisum, maxsum;

for (int i=0; i<5; i++) //i can be int because it's size of list i.e 5
{
    cin>>list[i];
}

minisum=minimini(list);
maxsum=maxa(list);

cout<<minisum<<" "<<maxsum;

【讨论】:

    【解决方案2】:

    int 类型有它的范围:

    int: -2,147,483,648 to 2,147,483,647
    

    如果使用 long long int 类型会更好。

    long long int: -(2^63) to (2^63)-1
    

    以下是我的测试代码,参考 LernerCpp 的 cmets 附加 typedef 语句:

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<string>
    using namespace std;
    
    typedef long long int INT64;
    
    INT64 minimini(INT64 list[]){
        INT64 minisum=0;
        INT64 taker;
        INT64 a=max({list[0],list[1],list[2],list[3],list[4]});
        for (int i=0; i<5; i++){
            taker=list[i];
            if(taker!=a){
                minisum=minisum+taker;
            }
        }
    return minisum;
    }
    INT64 maxa(INT64 list[]){
        INT64 maxsum=0;
        INT64 taker;
        INT64 a=min({list[0],list[1],list[2],list[3],list[4]});
        for (int i=0; i<5; i++){
            taker=list[i];
            if(taker!=a){
                maxsum=maxsum+taker;
                cout<<"maxsum >>"<<maxsum<<endl;
                cout<<"a="<<a<<endl;
            }
        }
    return maxsum;
    }
    int main(){
        INT64 list[5];
        INT64 minisum, maxsum;
        // int: -2,147,483,648 to 2,147,483,647
        // long long int:   -(2^63) to (2^63)-1
        for (int i=0; i<5; i++){
            std::string tmp;
            char* pEnd=0;
            printf("enter number %d:\n",i);
            cin>>tmp;
            list[i]=strtoll(tmp.c_str(),&pEnd,10);
            printf("number %d: %lld\n",i,list[i]);
        }
    
        printf("the list array are: [%lld,%lld,%lld,%lld,%lld,]\n",list[0],list[1],list[2],list[3],list[4]);
    
        minisum=minimini(list);
        maxsum=maxa(list);
    
        cout<<minisum<<" "<<maxsum;
    
    
        return 0;
    }
    

    Live Demo on coliru

    结果:

    C:\Users\s41167\Documents\mingw-w64>test_maximum.exe
    enter number 0:
    10000000000
    number 0: 10000000000
    enter number 1:
    -10000000000
    number 1: -10000000000
    enter number 2:
    20000000000
    number 2: 20000000000
    enter number 3:
    -20000000000
    number 3: -20000000000
    enter number 4:
    30000000000
    number 4: 30000000000
    the list array are: [10000000000,-10000000000,20000000000,-20000000000,300000000
    00,]
    maxsum >>10000000000
    a=-20000000000
    maxsum >>0
    a=-20000000000
    maxsum >>20000000000
    a=-20000000000
    maxsum >>50000000000
    a=-20000000000
    0 50000000000
    C:\Users\s41167\Documents\mingw-w64>
    

    还有 ANIKET LAVKUSH VISHWAKARMA 19B 的意见:

    C:\Users\s41167\Documents\mingw-w64>test_maximum.exe
    enter number 0:
    256741038
    number 0: 256741038
    enter number 1:
    623958417
    number 1: 623958417
    enter number 2:
    467905213
    number 2: 467905213
    enter number 3:
    714532089
    number 3: 714532089
    enter number 4:
    938071625
    number 4: 938071625
    the list array are: [256741038,623958417,467905213,714532089,938071625,]
    maxsum >>623958417
    a=256741038
    maxsum >>1091863630
    a=256741038
    maxsum >>1806395719
    a=256741038
    maxsum >>2744467344
    a=256741038
    2063136757 2744467344
    C:\Users\s41167\Documents\mingw-w64>
    

    【讨论】:

    • 您没有输入 long long long int,而是使用了类型别名!
    【解决方案3】:

    虽然int 范围确实是一个问题,但我很难理解的是为什么您不会使用任何新的 C++ 功能,例如:

    #include <iostream>
    #include <array>
    #include <algorithm>
    #include <numeric>
    
    using lli_t = long long int;
    
    int main(){
        std::array<int,5> list;
    
        for (int i=0; i<list.size(); i++){
            std::cin>>list[i];
        }
    
        std::sort(std::begin(list), std::end(list));
    
        auto minsum = std::accumulate(std::begin(list), std::begin(list)+4, static_cast<lli_t>(0));
        auto maxsum = std::accumulate(std::begin(list)+1, std::end(list), static_cast<lli_t>(0));
    
        std::cout << minsum << " " << maxsum;
    
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      整数数据类型只能保存从 -2,147,483,647 到 2,147,483,647 [1] 的值。解决此问题的一种简单方法是将所有 int 声明更改为 floatdoublelong 数据类型。

      [1]https://www.ibm.com/support/knowledgecenter/en/SSGU8G_12.1.0/com.ibm.sqlr.doc/ids_sqr_122.htm

      【讨论】:

      • long 在某些平台上也有 32 位(例如在我的 Windows/VS2013 上)。为了安全起见,我更喜欢long longstd::int64_t
      • 你到底为什么要链接到 SQL 引用?
      • @Scheff 使用 long long 或 std::int64_t 仍然为这些测试用例提供相同的错误输出
      • float 有 23 位尾数。因此,它不能精确地存储 32 位整数。我也不认为这是合适的选择。
      • @ANIKETLAVKUSHVISHWAKARMA19B 诀窍是将加法的 参数 转换(转换)到long long。否则,您会将 32 位加法(有溢出问题)存储到 64 位变量中。
      猜你喜欢
      • 2020-10-03
      • 1970-01-01
      • 2020-02-09
      • 2021-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-25
      相关资源
      最近更新 更多