0

I am writing a simple C++ program that should combine all elements of an integer array to form one number. Eg. {4,5,6} --> should be 456. But my output is one less than the original number. i.e instead of 456, I am getting 455. Sometimes my program works fine and sometimes not. Can someone please explain to me what is causing this unpredictible behaviour? Thank You!!

Please take a look at my code:

#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 

}
Jimmy15
  • 19
  • 4
  • 4
    `pow`, here, is a bad choice. It returns a `double`, which is truncated to an `int`, maybe the "wrong" one, in this code. Note that you can obtain a power of ten using only integral type variables multiplying 1 by 10 multiple times. – Bob__ Jan 01 '22 at 09:04

5 Answers5

2

As mentioned by Bob__, pow is a function for doubles and other floating-point types. For this specific algorithm, instead, we can do this:

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];

}

At each step, this multiplies the previous number by 10, and makes the digit correct at that place. E.g.

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
fabian
  • 80,457
  • 12
  • 86
  • 114
jh316
  • 901
  • 7
  • 9
0

From this simple problem you can already learn quite a bit to improve your C++ code. Example :

// #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;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
  • I aggree with every suggestion here, but you fail to answer the question (or at least it's too hard to find it in the answer). The question is: *"Can someone please explain to me what is causing this unpredictible behaviour?"* – fabian Jan 01 '22 at 11:22
  • I considered that answered. Using floating point calculations as part of an integer calculation should be done with care (if at all necessary). – Pepijn Kramer Jan 01 '22 at 11:35
0

Here when you call pow;

pow(10,lengthA-1-x)

your code is probably calling the following overload of std::pow:

double pow ( double base, int iexp );

And as can be seen, it returns a floating-point value which might have a rounding error. I ran your code on my system and the results were correct. However, your code might generate different results on different platforms. And it seems that this is the case in your system.

Instead, you can do this:

#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;
}

As a result of using constexpr keyword, the above function will be evaluated at compile-time (whenever possible, which is the case in the above code).

Note regarding constexpr: Use const and constexpr keywords wherever possible. It's a very good practice. Read about it here constexpr (C++).

Note: If you are not familiar with std::span then check it out here.

digito_evo
  • 3,216
  • 2
  • 14
  • 42
0

Here is another way for this problem. You can use string to convert this numbers as you need.

With this loop, we convert each number to string and pase it to end of the num string. At the end, you have the number as you need as string. If you need that number as integer, you can conver it back at the end of the loop. To conver string to int you can check this :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;
}
Gresta
  • 72
  • 8
0

In addition to jh316's solution;

#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;
}

Description of the code:

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