How to detect integer overflow? [duplicate] - c++

This question already has answers here:
How to detect integer overflow in C [duplicate]
(3 answers)
Closed 1 year ago.
Write a program that reads and stores a series of integers and then computes the sum of the first N integers. First ask for N, then read
the values into a vector, then calculate the sum of the first N
values. For example: “Please enter the number of values you want to
sum:” 3 “Please enter some integers (press '|' to stop):” 12 23 13 24
15 | “The sum of the first 3 numbers ( 12 23 13 ) is 48.” Handle all
inputs. For example, make sure to give an error message if the user
asks for a sum of more numbers than there are in the vector.
Modify the program from exercise 8 to write out an error if the result cannot be represented as an int.
So in exercise 9 it says to write out an error message if the result cannot be represented as an int, but if I'm only adding up integers here the only thing I can think of here that would cause a number to not be able to be represented as an int would be if there's some integer overflow and the integer goes above INT_MAX or below INT_MIN but how exactly can I detect this?
This is my code:
#include<vector>
#include<cmath>
#include<string>
#include<iostream>
#include<algorithm>
#include<stdexcept>
using namespace std;
int main()
{
int N = 0;
vector<int> values;
cout << "Please enter the number of values you want to sum." << '\n';
cin >> N;
cout << "Please enter some numbers" << '\n';
for (int tempnum; cin >> tempnum; )
{
values.push_back(tempnum);
}
if (N > values.size())
{
cout << "How am I gonna add up more numbers than you gave me?" << '\n';
}
else
{
int total = 0;
for (int i = 0; i < N; i++)
{
total += values[i];
}
}
}
But I can't just check if total is above or below INT_MAX or INT_MIN because INT_MAX +1 or something returns some random negative value so I'm not really sure how to do this

You can do this with some arithmetic:
So you want to know if acc + x > INT_MAX, where acc is the accumulator (the sum so far) and x is the next element. Adding them together may overflow though. But acc > INT_MAX - x is equivalent and x is already stored in an int. So this can also not underflow, bc. x can be at most INT_MAX.
I.e., just transform the inequation to avoid overflow. In this case, subtract x from both sides.
That only works for positive x though, thanks to user interjay for pointing this out.
With negative x, this becomes a subtraction:
acc + (-x) > INT_MAX
acc - x > INT_MAX
This can not overflow, because we are subtracting from acc. But it may underflow, so the question becomes:
acc - x < INT_MIN
acc < INT_MIN + x
So:
int acc = 0;
for (int i = 0; i < N; ++i) {
int x = values[i];
if (x >= 0 && acc > (INT_MAX - x)) {
cout << "ERROR: Overflow.";
return 1;
} else if (x < 0 && acc < (INT_MIN - x)) {
cout << "ERROR: Underflow.";
return 1;
} else {
acc += x;
}
}

Related

Making a factorial program faster?

I've been trying to submit this to a website with programming lessons, but the judge keeps telling me that this program takes too long to execute :/
Problem Statement:
Write a program that reads a non-negative integer n from the standard input, will count the digit of tens and the digit of ones in the decimal notation of n!, and will write the result to the standard output. In the first line of input there is one integer D (1≤D≤30), denoting the number of cases to be considered. For each case of entry. your program should print exactly two digits on a separate line (separated by a single space): the tens digit and the ones digit of n! in the decimal system.
Input/Output:
Input
Output
2
1
0 1
4
2 4
#include <iostream>
using namespace std;
int d,n;
int main()
{
cin>>d;
for(int i=0; i<d; i++)
{
cin>>n;
int silnia = 1;
for(int j=n; j>1; j--)
{
silnia=silnia*j;
}
if(silnia == 1) cout<<0<<" "<<silnia<<"\n";
else cout<<(silnia/10)%10<<" "<<silnia%10<<"\n";
}
return 0;
}
You can get rid of inner loop since n! == (n - 1)! * n:
cin >> d;
int factorial = 1;
cout << 0 << " " << 1 << "\n";
for (int i = 1; i < d; ++i) {
/* we operate with last two disgits: % 100 */
factorial = (factorial * i) % 100;
cout << factorial / 10 << " " << factorial % 10 << "\n";
}
Edit: Another issue is with
silnia=silnia*j;
line. Factorial grows fast:
13! = 6227020800 > LONG_MAX (2147483647)
that's why we should use modulo arithmetics: we keep not factorial itself (which can be very large), but its two last digits (note % 100), which is garanteed to be in 00..99 range:
factorial = (factorial * i) % 100;
Or even (if i can be large)
factorial = (factorial * (i % 100)) % 100;
Since only the last 2 digits of n! are needed, any n >= 10** will have a n! with 00 as the last 2 digits.
A short-cut is to test n: This takes the problem from O(n) to O(1).
int factorial = 0;
if (n < 10) {
int factorial = 1;
for(int j=n; j>1; j--)
{
factorial *= j;
}
factorial %= 100;
}
Or use a look-up table for n in the [0...10) range to drop the for loop.
---
** 10_or_more! has a 2 * 5 * 10 * other factors in it. All these factorials then end with 00.

How to find out if the input number is balanced?

According to my lecturer a balanced number is balanced if the sum of its divisors is equal to it self. for example: 6 is a balanced number because 1+2+3=6
These are my very first homework so i am struggeling.
#include <iostream>
using namespace std;
int main() {
int num = 0;
int sum = 0;
cout << "Enter a number" << endl;
cin >> num;
if (num % (num-1) == 0 ){
for(int i =1; sum == 0; i++) {
sum += (num - i);
}
if (sum == num) {
cout << "Great Success" << endl;
}
else {
cout << "Wrong number" << endl;
}
}
}
Do the maths first. Often code being a bit messy is just a consequence of not preparing yourself good enough to write the code. Dont start writing code before you know what you want to write. Frankly, from your code one can see that it is something related to num-1 dividing num, but otherwise it is not clear how it is supposed to solve the problem. And its intendation makes it quite hard to read, so lets forget about the code and start from scratch...
y is a divisor of x exactly if x % y == 0. The biggest possible divisor of x is x/2. To get all divisors we can simply check every number from 2 up to x/2 (1 is always considered a divisor, hence no need to check).
Only now we can write some code:
int x;
std::cin >> x;
int sum = 1;
for (int y = 2; y <= x/2; ++y){
if ( check_if_y_is_divisor) { sum += y; }
}
bool is_balanced = sum == x;
I left a tiny hole in the code that you have to fill (I just dont like to give away the full solution when it is homework).

C++ program doesn't fully execute iteration [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
The program I've written is supposed to take in two user inputs (one being the number we're meant to check whether it's k-hyperperfect or not, the other being a maximum k-value.) if the input integer is k-hyperperfect in the range of 1 to the inputted maximum k-value, then the output should be that k-value. For example, if the input integer is 21 and the maximum k-value is 100 then the output should be 2.
My program gives the correct output for (the first number is the input integer, the second number is the k-max value, the third number is output value) ...
21 (input integer) 100 (k-max) --> 180
301 100 --> 6
12211188308281 100 --> 0
-301 100 --> 0
21 -5 --> 0
However, it doesn't correctly execute for 12211188308281 and 200 (it gives me 0 when it should give me 180). I've run my code through a step by step visualizer and it seems to just abruptly stop execution when i = 496 in the for loop within the else statement. But I don't understand why since it executes correctly for 5 other test runs.
#include <iostream>
using std::cout; using std::cin; using std::endl; using std::fixed;
int main () {
int number;
int kmax;
int sum = 0 ;
int hyper = 0;
std::cin >> number;
std::cin >> kmax;
if (number <= 6 or kmax < 1) {
std::cout << "0" << "\n";
}
else {
for (int i=1;i<=number;i++) {
if (number%i==0 and i != 1 and i != number){
sum+= i;
}
}
}
for (int k=1; k <= kmax; k++) {
hyper = ((sum)*k) + 1;
if (hyper == number) {
std::cout << k << endl;
break;
}
}
}
You need to check that numbers read through std::istreams (like std::cin) are read successfully. As the value that you enter for number is too large to store in an integer your read will fail. For example you could change your code to:
int main()
{
int number;
std::cin >> number;
if ( !std::cin )
{
std::cout << "invalid value: " << number << "\n";
return 1;
}
else
{
std::cout << "valid value: " << number << "\n";
}
// calculate answer
return 0;
}
You would then see your program printing "invalid value: 2147483647" if you have a c++11 compliant compiler or an undefined number if you have an older compiler.
Now that you have implemented reading values correctly the fix to your issue is to use a larger integer type like int64_t which is able to hold your number.
As already noted, the int type in your machine isn't big enough to store the value 12,211,188,308,281.
The C++ standard only mandates it to be capable of storing a value up to 32,767 and even in the (now common) case of a 32-bit int or long int), the limit would be 2,147,483,647. So you need a long long int or an int64_t (if it's present in your implementation).
A simple check like
if (std::cin >> number >> kmax ) { // perform calculations...
Would have shown the error sooner.
That beeing said, there are also some simple changes that could be done to the posted code in order to make it more efficient. The first loop can be optimized considering the "symmetry" of the divisors of a given number: meaning, if n is divisible by a, so that b = n/a is a whole number, b too is a divisor of n. This will limit the number of iterations to the square root of n, instead of n.
long long int number,
kmax,
sum = 0;
// ...
long long int temp = number,
i = 2;
for (; i * i < number; i++) {
if (number % i == 0) {
temp = number / i;
sum += i + temp;
}
}
if (i * i == number) {
sum += i;
}
There probably are better algorithms, but I'm unfamiliar with those.
The second loop, in my opinion, is unnecessary. The value k can be calculated directly:
if ( (number - 1) % sum == 0) {
std::cout << (number - 1) / sum << '\n';
}
You are assigning a too long value 12211188308281 to integer "number", which can't contain it fully and it is getting truncated to 596285753. You can add a print statement to print it.
std::cout<<number;
which will print 596285753.
As suggested you should use long long int. Again its dependent on the software platform running on your system.

basic nestled loop calculate prime numbers between 1 - 239, inclusive

I am working on a program in which I must print out the number of primes, including 1 and 239, from 1 - 239 ( I know one and or two may not be prime numbers, but we will consider them as such for this program) It must be a pretty simple program because we have only gone over some basics. So far my code is as such, which seems like decent logical flow to me, but doesnt produce output.
#include <iostream>
using namespace std;
int main()
{
int x;
int n = 1;
int y = 1;
int i = 0;
while (n<=239)
{x = n % y;
if (x = 0)
i++;
if (y < n)
y++;
n++;
while (i == 2)
cout << n;
}
return 0;
}
The way I want this to work is to take n, as long as n is 239 or less, and preform modulus division with every number from 1 leading up to n. Every time a number y goes evenly into n, a counter will be increased by 1. if the counter is equal to 2, then the number is prime and we print it to the screen. Any help would be so greatly appreciated. Thanks
std::cout << std::to_string(2) << std::endl;
for (unsigned int i = 3; i<240; i += 2) {
unsigned int j = 3;
int sq = sqrt(i);
for (; j <= sq; j += 2) if (!(i%j)) break;
if (j>sq) std::cout << std::to_string(i) << std::endl;
}
first of all, the prime definition: A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
so you can skip all the even numbers (and hence ... i+=2).
Moreover no point to try to divide for a number greater than sqrt(i), because then it will have a divisor less than sqrt(i) and the code finds that and move to the next number.
Considering only odd numbers, means that we can skip even numbers as divisors (hence ... j+=2).
In your code there are clearly beginner errors, like (x = 0) instead of x==0. but also the logic doesn't convince. I agree with #NathanOliver, you need to learn to use a debugger to find all the errors. For the rest, good luck with the studies.
lets start with common errors:
first you want to take input from user using cin
cin>>n; // write it before starting your while loop
then,
if (x = 0)
should be:
if (x == 0)
change your second while loop to:
while (i == 2){
cout << n;
i++;
}

Using char arrays to add together large numbers

I have an assignment in which I am supposed to
1.) Read in 2 char arrays of numbers
2.) add together the arrays, performing carry addition, carrying the tens place
3.) print out the newly added array.
I am also supposed to print an error if I need to carry on the last digit of the array (overflow)
so something like 99999999999999999999 +
1 =
________________________
ERROR
That's the part I'm having trouble with.
The above outputs something like "99999999999999999:0" so I have no idea what's going wrong.
I'll post my code, but please be nice :( I know it certainly isn't the most efficient, but I'm just trying to lay things out in a way that is easy for my brain to understand right now.
And yes, I HAVE to use char arrays. I guess it's to help us understand the ascii table.
#include <iostream>
using namespace std;
void InitNumber(char[]);
int AddArrays(char first[], char second[], char combined[]);
void OutputNumber (char[]);
const int LENGTH = 20; // global variable
int main()
{
char set1[LENGTH];
char set2[LENGTH];
char sum[LENGTH];
InitNumber (set1);
InitNumber (set2);
if(AddArrays (set1, set2, sum)) {
cout << "overflow!" << endl;
}
OutputNumber(sum);
}
void InitNumber (char list[])
{
int numberOfDigits;
cout << "Please enter the number of digits in the number: ";
cin >> numberOfDigits;
cout << "Please enter the digits in the number with the LEAST significant first: ";
for (int i = 0; i < numberOfDigits; i++) {
cin >> list [i];
}
for (int l=(numberOfDigits); l < LENGTH; l++) {
list [l] = '0';
}
}
int AddArrays(char first[], char second[], char combined[])
{
for (int h = 0; h < LENGTH; h++)
combined[h]= '0';
int overflow = 0;
for (int i = 0; i < LENGTH; i++) {
int currentSum = (first[i]-'0' + second[i]-'0');
cout << "currentSum = " << currentSum << endl;
if(currentSum / 10 == 0 )
combined[i] += currentSum;
else if (currentSum/10 !=0) {
if (i == LENGTH-1 && currentSum/10 !=0){
overflow = 1;
}
else{
combined [i] += currentSum%10;
cout << "current i: " << combined[i] << endl;
combined [i+1] += currentSum/10;
cout << "current i+1: " << combined[i+1] << endl;
}
}
}
return overflow;
}
void OutputNumber(char arrayOut[])
{
for (int l=LENGTH - 1; l >= 0; l--)
cout << arrayOut[l];
}
working input
input
6
1 2 3 4 5 6
7
1 2 3 4 5 6 7
output
00000000000008308642
Not-working output
input
20
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
1
1
output
999999999999999999:0
I'm going to reproduce small parts of your inner loop where you are carrying out the addition, in order to explain why your overflow detection is broken.
for (int i = 0; i < LENGTH; i++) {
int currentSum = (first[i]-'0' + second[i]-'0');
if(currentSum / 10 == 0 )
combined[i] += currentSum;
Here you're adding the corresponding pair of digits from the two numbers you're adding, and checking (in your particular style) if they overflowed. Try to remember this part, it's important. In order to check for overflow, you're only checking the result of adding the pair of digits from the two large numbers you're adding.
else if (currentSum/10 !=0) {
This is a completely useless check. You can only get here if the division is known to produce a non-zero result. This if() can be removed completely. Now, the relevant part of your code is
combined [i] += currentSum%10;
combined [i+1] += currentSum/10;
Do you see the problem yet?
Your approach is, once overflow is detected, is to increment the next higher order digit in the result.
Unfortunately, on the next loop iteration, in order to check for carry over, you're just checking the sum of the next corresponding digit pair, from the two large numbers you're adding. The carry-over you're saving here is going to get completely ignored.
Say your numbers are two digits long max, rather than 20, and you entered the numbers 99 and 1.
On the first iteration, you'll add 9 and 1, save 0 as the first digit, and add 1 to the second digit in the sum.
On the second iteration, you'll add 9 and 0, and, given your logic above, conclude that nothing overflowed.