【问题标题】:Combining elements of an integer array into a single integer variable将整数数组的元素组合成一个整数变量
【发布时间】:2022-01-01 08:50:05
【问题描述】:

我正在编写一个简单的 C++ 程序,它应该将整数数组的所有元素组合成一个数字。 例如。 {4,5,6} --> 应该是 456。但是我的输出比原始数字少一。即我得到 455 而不是 456。有时我的程序运行良好,有时却不行。有人可以向我解释导致这种不可预测行为的原因吗?谢谢!!

请看我的代码:

#include <bits/stdc++.h>
#include <cmath>
using namespace std;

int main()
{
    int A[5] = {4,5,6,7,8};
    int lengthA = 5;
    int num = 0;
    
    for(int x = 0; x < lengthA; x++)
    {
        
        num = A[x]*pow(10,lengthA-1-x) + num;

    }
    printf("%d\n", num ); // My O/P is 45677 

}

【问题讨论】:

  • pow,在这里,是一个糟糕的选择。它返回一个double,在此代码中被截断为int,可能是“错误的”。请注意,您可以仅使用整数类型变量将 1 乘以 10 多次获得 10 的幂。

标签: c++ arrays for-loop pow


【解决方案1】:

正如 Bob__ 所提到的,pow 是一个用于双精度和其他浮点类型的函数。对于这个特定的算法,我们可以这样做:

int A[5] = {4,5,6,7,8};
int lengthA = 5;
int num = 0;

for(int x = 0; x < lengthA; x++)
{
    
    num = num*10 + A[x];

}

在每一步,这都会将前一个数字乘以 10,并使该数字在该位置正确。 例如

Step 1: num = 0*10 + 4 == 4 
Step 2: num = 4 * 10 + 5 == 40 + 5 == 45
Step 3: num = 45 * 10 + 6 == 450 + 6 == 456
Step 4: num = 456 * 10 + 7 == 4560 + 7 == 4567
Step 5: num == 4567 * 10 + 8 == 45670 + 8 == 45678

【讨论】:

    【解决方案2】:

    从这个简单的问题中,您已经可以学到很多东西来改进您的 C++ 代码。 示例:

    // #include <bits/stdc++.h>  // NO : https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h
    // using namespace std // NO : https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
    
    #include <iostream> // include only what you need for std::cout
    
    int main()
    {
        int values[]{ 4,5,6,7,8 }; // no need for an =
        int num{ 0 };
    
        // prefer range based for loops
        // they will not run out of bounds
        // https://en.cppreference.com/w/cpp/language/range-for
        for (const int value : values) 
        {
            num *= 10;
            num += value;
        }
    
        // avoid printf, use std::cout with C++20 std::format for formatting
        // https://stackoverflow.com/questions/64042652/is-printf-unsafe-to-use-in-c
        // https://en.cppreference.com/w/cpp/utility/format/format
        std::cout << "num = " << num << "\n";
    
        return 0;
    }
    

    【讨论】:

    • 我同意这里的每一个建议,但你没有回答这个问题(或者至少在答案中很难找到它)。问题是:“有人可以向我解释导致这种不可预测行为的原因吗?”
    • 我认为已经回答了。使用浮点计算作为整数计算的一部分应该小心(如果有必要的话)。
    【解决方案3】:

    这是解决此问题的另一种方法。您可以根据需要使用string 转换此数字。

    通过这个循环,我们将每个数字转换为 string 并将其粘贴到数字 string 的末尾。最后,您将获得所需的号码string。如果您需要该号码为integer,您可以在循环结束时将其转换回来。要将string 转换为int,您可以查看:Converting String to Numbers

    #include <iostream> //include to use cout
    #include <string> // include to use string
    
    using namespace std;
    
    int main() {
    
      int A[5] = {4,5,6,7,8}; // input array
      int lengthA = sizeof(A) / sizeof(A[0]); // size of array
    
      std::string num = "";
    
      for(int i=0; i<lengthA; i++){
        num += std::to_string(A[i]);
      }
    
      std::cout << "Number : " << num;
    }
    

    【讨论】:

      【解决方案4】:

      除了jh316的解决方案;

      #include <iostream>
      
      using namespace std;
      
      int A[] = {4,5,6,7,8};
      int num = 0;
      
      int main()
      {
          for(int i: A){
              num = num * 10 + i;
          }
          cout << num;
      }
      

      代码说明:

      Initial state of the variable: num = 0
      
      For each iteration the num variable is:
      
      1. num = 0 * 10 + 4    = 4
      2. num = 4 * 10 + 5    = 45
      3. num = 45 * 10 + 6   = 456
      4. num = 456 * 10 + 7  = 4567
      5. num = 4567 * 10 + 8 = 45678
      

      【讨论】:

        【解决方案5】:

        这里当你打电话给pow;

        pow(10,lengthA-1-x)
        

        您的代码可能正在调用std::pow 的以下重载:

        double pow ( double base, int iexp );
        

        可以看出,它返回一个可能有舍入误差的浮点值。我在我的系统上运行了你的代码,结果是正确的。但是,您的代码可能会在不同平台上生成不同的结果。您的系统似乎就是这种情况。

        相反,您可以这样做:

        #include <cstdio>
        #include <array>
        #include <span>
        
        
        constexpr int convertDigitsToNumber( const std::span<const int> digits )
        {
            int resultNum { };
        
            for ( const auto digit : digits )
            {
                resultNum = resultNum * 10 + digit;
            }
        
            return resultNum;
        }
        
        int main( )
        {
            constexpr std::size_t arraySize { 5 };
            // use std::array instead of raw arrays
            constexpr std::array<int, arraySize> arrayOfDigits { 4, 5, 6, 7, 8 };
        
            constexpr int num { convertDigitsToNumber( arrayOfDigits ) };
        
            std::printf( "%d\n", num );
        
            return 0;
        }
        

        由于使用了constexpr 关键字,上面的函数将在编译时进行评估(只要可能,上面的代码就是这种情况)。

        关于constexpr 的注意事项: 尽可能使用constconstexpr 关键字。这是一个非常好的做法。阅读这里constexpr (C++)

        注意:如果您不熟悉std::span,请查看here

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-12-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-07-21
          • 2020-10-27
          相关资源
          最近更新 更多