Getting strange values in calculator program

Hello, I made a calculator that can use the last calculated value over and over again a bunch of times, but after awhile it starts giving some weird values.
I really dont know how else to word it, heres the code if anyones interested
enough to compile and see whats up.

Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "stdafx.h"
#include <iostream>
#include "Operation.h"
using namespace std;


void    display_operation();
void    display_operand(int x, int y, int z);
int     set_operand(int x, int y, int z);
double  set_operand(int x, double y, double z);

Operation calculate;

int main()
{
	bool on;
	int choice;
	int num[1000] = {};
	int i = 0;
	int j = 1;

	cout << "-< Basic Arithmetic Calculator >-\n"     << endl;
	cout << "Press 1 to start or enter to exit" << endl;
	 cin >> on;
	cout << endl << endl;

	while (on == true) {
		if (i == 0) {
			cout << "\nEnter number\n" << endl;
			cin >> num[i];
			display_operation();
			cin >> choice;
			cout << "\nEnter number\n" << endl;
			cin >> num[j];
			display_operand(choice, num[i], num[j]);
			i++;
			num[i] = set_operand(choice, num[j], num[i]);
			j++;
		}
		else {
			display_operation();
			cin >> choice;
			cout << "\nEnter number\n" << endl;
			cin >> num[j];
			display_operand(choice, num[i], num[j]);

			num[j] = set_operand(choice, num[j], num[i]);
			j++;
			i++;
		}
	}
}

void display_operation() {
	cout << "\n1 = Addition:       +" << endl;
	cout << "2 = Subtraction:    -" << endl;
	cout << "3 = Multiplication: *" << endl;
	cout << "4 = Division:       %" << endl;
	cout << "5 = Modulus:        r" << endl;
}
void display_operand(int x, int y, int z) {
	switch(x) {
	case 1:
		cout << "\n\n" << y << " + " << z << " = " << calculate.addition(y, z) <<
		endl << endl;
		break;
	case 2:
		cout << "\n\n" << y << " - " << z << " = " << calculate.subtraction(y, z) <<
		endl << endl;
		break;
	case 3:
		cout << "\n\n" << y << " x " << z << " = " << calculate.multiplication(y, z) <<
		endl << endl;
		break;
	case 4:
		cout << "\n\n" << y << " % " << z << " = " << calculate.division(y, z) <<
		endl << endl;
		break;
	case 5:
		cout << "\n\n" << y << " r " << z << " = " << calculate.modulus(y, z) << 
		endl << endl;
		break;
	}
}

int set_operand(int x, int y, int z) {
	int temp = 0;
	switch (x) {
	case 1:
		temp = calculate.addition(y, z);
		break;
	case 2:
		temp = calculate.subtraction(y, z);
		break;
	case 3:
		temp = calculate.multiplication(y, z);
		break;
	case 4:
		temp = calculate.division(y, z);
		break;
	case 5:
		temp = calculate.modulus(y, z);
		break;
	}
	return temp;
}
double set_operand(int x, double y, double z) {
	double temp = 0;
	switch (x) {
	case 1:
		temp = calculate.addition(y, z);
		break;
	case 2:
		temp = calculate.subtraction(y, z);
		break;
	case 3:
		temp = calculate.multiplication(y, z);
		break;
	case 4:
		temp = calculate.division(y, z);
		break;
	}
	return temp;
}


Operation.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#pragma once
class Operation
{
public:
	int addition(int x, int y) {
		return x += y;
	}
	double addition(double x, double y) {
		return x += y;
	}
	int subtraction(int x, int y) {
		return x -= y;
	}
	double subtraction(double x, double y) {
		return x -= y;
	}
	int mutiplication(int x, int y) {
		return x *= y;
	}
	double multiplication(double x, double y) {
		return x *= y;
	}
	int division(int x, int y) {
		return x /= y;
	}
	double division(double x, double y) {
		return x /= y;
	}
        int modulus(int x, int y) {
		return x %= y;
	}
};
Last edited on
Just had a runtime error after putting in the input for 5 + 5 - 5.
"Stack around the variable "on" was corrupted"
Revised and it made it slightly better, no more runtime error and can go a little longer without funky outputs.

Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include "stdafx.h"
#include <iostream>
#include "Operation.h"
#include "UI.h"
using namespace std;

Operation calculate;
UI ui;

void first_operation();
void consecutive_operation();
void off();

bool on = false;
int choice;
int num[1000] = {};
int i = 0;
int j = 1;

int main()
{
	cout << "-< Basic Arithmetic Calculator >-\n" << endl;
	cout << "Press 1 to start or enter to exit"      << endl;
	cin    >> on;
	cout << endl << endl;
	
	while (on == true) {
		if (i == 0) {
			first_operation();
		}
		else {
			consecutive_operation();
		}
	}
}

void first_operation() {
	cout << "\nEnter number\n" << endl;
	cin    >> num[i];

	ui.display_operation();
	cin   >> choice;
	off();

	cout << "\nEnter number\n" << endl;
	cin    >> num[j];

	ui.display_operand(choice, num[i], num[j]);
	
	i++;
	num[i] = calculate.set_operand(choice, num[j], num[i]);
	j++;
}

void consecutive_operation() {
	ui.display_operation();
	cin  >> choice;
	off();

	cout << "\nEnter number\n" << endl;
	cin  >> num[j];

	ui.display_operand(choice, num[i], num[j]);

	num[j] = calculate.set_operand(choice, num[j], num[i]);
	j++;
	i++;
}

void off() {
	if (choice == 0) {
		on = false;
	}
}


Operation.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#pragma once
class Operation
{
public:
	int     set_operand   (int x, int y, int z);
	double  set_operand(int x, double y, double z);

	int addition	     (int x, int y) {
		return x += y;
	}
	double addition	      (double x, double y) {
		return x += y;
	}
	int subtraction	      (int x, int y) {
		return x -= y;
	}
	double subtraction   (double x, double y) {
		return x -= y;
	}
	int mutiplication	      (int x, int y) {
		return x *= y;
	}
	double multiplication(double x, double y) {
		return x *= y;
	}
	int division		      (int x, int y) {
		return x /= y;
	}
	double division	      (double x, double y) {
		return x /= y;
	}
	int modulus	      (int x, int y) {
		return x %= y;
	}
};


Operation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "stdafx.h"
#include "Operation.h"


int Operation::set_operand(int x, int y, int z) {
	int temp = 0;
	switch (x) {
	case 1:
		temp = addition		(y, z);
		break;
	case 2:
		temp = subtraction	(y, z);
		break;
	case 3:
		temp = multiplication(y, z);
		break;
	case 4:
		temp = division	       (y, z);
		break;
	case 5:
		temp = modulus      (y, z);
		break;
	}
	return temp;
}
double Operation::set_operand(int x, double y, double z) {
	double temp = 0;
	switch (x) {
	case 1:
		temp = addition		(y, z);
		break;
	case 2:
		temp = subtraction	(y, z);
		break;
	case 3:
		temp = multiplication(y, z);
		break;
	case 4:
		temp = division		(y, z);
		break;
	}
	return temp;
}


UI.h
1
2
3
4
5
6
7
#pragma once
class UI
{
public:
	void    display_operation();
	void    display_operand(int x, int y, int z);
};


UI.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "stdafx.h"
#include <iostream>
#include "UI.h"
#include "Operation.h"
using namespace std;

Operation calculation;

void UI::display_operation() {
	cout << "\n1 = Addition:       +" << endl;
	cout << "2 = Subtraction:    -"   << endl;
	cout << "3 = Multiplication: *"   << endl;
	cout << "4 = Division:       %"	 << endl;
	cout << "5 = Modulus:        r"    << endl;
	cout << "      0 to exit      "        << endl;
}
void UI::display_operand(int x, int y, int z) {
	switch (x) {
	case 1:
		cout << "\n\n" << y << " + " << z << " = " << calculation.addition(y, z)	       <<
			endl << endl;
		break;
	case 2:
		cout << "\n\n" << y << " - " << z << " = " << calculation.subtraction(y, z)    <<
			endl << endl;
		break;
	case 3:
		cout << "\n\n" << y << " x " << z << " = " << calculation.multiplication(y, z) <<
			endl << endl;
		break;
	case 4:
		cout << "\n\n" << y << " % " << z << " = " << calculation.division(y, z)	       <<
			endl << endl;
		break;
	case 5:
		cout << "\n\n" << y << " r " << z << " = " << calculation.modulus(y, z)        <<
			endl << endl;
		break;
	}
}
Hello MoreUmph,

I have not yet figured out where the problem is taking place, but the concept is that if I add until the total is 40 and then try to subtract 10 the answer is -30 when it should be 30.

Somewhere the numbers are getting reversed, so that you are subtracting 40 from 10 when you should be subtracting 10 from 40. So far I have only checked the integer addition and subtraction,butt the same concept could be happening with other calculations.

One problem I am having is trying to keep straight variable name of "x", "y" and "z". Not much meaning here when something like "firstOpp" and "secOpp" would help keep calculations in order and help to understand if you are subtracting 40 from 10 or 10 from 40.

The global variables make the program easier except for the fact the anywhere in the program can change these variables. This was my first thought of the problem until I realized that this was working right.

I will have to do some more tracing to find the problem.

Hope that helps for now,

Andy
A check for division by zero would be good :+)

I still haven't figured anything out, renamed some variables and made it easier to read.

@Handy Andy: I think the problems is some sort of semantics error with how I use the "i" and "j" variables in the first/consecutive functions(Line 37/55 in main)

A long time ago I read something about the standard arrays being dangerous somehow but I haven't looked into that at all.

@TheIdeasMan: Thats an awesome suggestion thanks, Ill work on that when I get this running properly.


Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include "stdafx.h"
#include <iostream>
#include "Operation.h"
#include "UI.h"
using namespace std;

Operation calculate;
UI ui;

void first_operation();
void consecutive_operation();
void off();

bool on = false;
int operation;
double num[1000] = {};
int i = 0;
int j = 1;

int main()
{
	cout << "-< Basic Arithmetic Calculator >-\n" << endl;
	cout << "Press 1 to start or enter to exit"   << endl;
	cin  >> on;
	
	while (on == true) {
	  if (i == 0) {
	    first_operation();
	  }
	  else {
	    consecutive_operation();
	  }
	}
}


void first_operation() {
	cout << "\n\nEnter number\n" << endl;
	cin  >> num[i];

	ui.display_operation();
	cin  >> operation;
	off();

	cout << "\nEnter number\n" << endl;
	cin  >> num[j];

	ui.display_operand(operation, num[i], num[j]);
	
	i++;
	num[i] = calculate.set_operand(operation, num[j], num[i]);
	j++;
}

void consecutive_operation() {
	ui.display_operation();
	cin  >> operation;
	off();

	cout << "\nEnter number\n" << endl;
	cin  >> num[j];

	ui.display_operand(operation, num[i], num[j]);

	num[j] = calculate.set_operand(operation, num[j], num[i]);
	j++;
	i++;
}

void off() {
	if (operation == 0) {
	    on = false;
	}
}


Operation.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#pragma once
class Operation
{
public:
  int     set_operand(int operation, int num1, int num2);
  double  set_operand(int operation, double num1, double num2);

	int addition		 (int num1, int num2)	    {
			return num1 += num2;
	}
	int subtraction		 (int num1, int num2)       {
			return num1 -= num2;
	}
	int mutiplication	 (int num1, int num2)       {
			return num1 *= num2;
	}
	int division		 (int num1, int num2)       {
			return num1 /= num2;
	}
	int modulus		     (int num1, int num2)   {
			return num1 %= num2;
	}
	double addition		 (double num1, double num2) {
			return num1 += num2;
	}
	double subtraction	 (double num1, double num2) {
			return num1 -= num2;
	}
	double multiplication(double num1, double num2)     {
			return num1 *= num2;
	}
	double division		 (double num1, double num2) {
			return num1 /= num2;
	}
};


Operation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "stdafx.h"
#include "Operation.h"

int Operation::set_operand(int operation, int num1, int num2) {
	int temp = 0;
	  switch (operation) {
		case 1:
			temp = addition		 (num1, num2);
		break;
		case 2:
			temp = subtraction	 (num1, num2);
		break;
		case 3:
			temp = multiplication    (num1, num2);
		break;
		case 4:
			temp = division		 (num1, num2);
		break;
		case 5:
			temp = modulus		 (num1, num2);
		break;
	}
  return temp;
}
double Operation::set_operand(int operation, double num1, double num2) {
	double temp = 0;
	  switch (operation) {
		case 1:
			temp = addition		 (num1, num2);
		break;
		case 2:
			temp = subtraction	 (num1, num2);
		break;
		case 3:
			temp = multiplication    (num1, num2);
		break;
		case 4:
			temp = division		 (num1, num2);
		break;
	}
  return temp;
}


UI.h
1
2
3
4
5
6
7
#pragma once
class UI
{
public:
  void    display_operation();
  void    display_operand(int operation, int num1, int num2);
};


UI.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "stdafx.h"
#include <iostream>
#include "UI.h"
#include "Operation.h"
using namespace std;

Operation calculation;

void UI::display_operation() {
	cout << "\n1 = Addition:       +" << endl;
	cout << "2 = Subtraction:    -"   << endl;
	cout << "3 = Multiplication: *"   << endl;
	cout << "4 = Division:       %"	  << endl;
	cout << "5 = Modulus:        r"   << endl;
	cout << "      0 to exit      "   << endl;
}
void UI::display_operand(int operation, int num1, int num2) {
  switch (operation) {
	case 1:
		cout << "\n\n" << num1 << " + " << num2 << " = " << calculation.addition(num1, num2)	   <<
		endl << endl;
	break;
	case 2:
		cout << "\n\n" << num1 << " - " << num2 << " = " << calculation.subtraction(num1, num2)	   <<
		endl << endl;
	break;
	case 3:
		cout << "\n\n" << num1 << " x " << num2 << " = " << calculation.multiplication(num1, num2) <<
		endl << endl;
	break;
	case 4:
		cout << "\n\n" << num1 << " % " << num2 << " = " << calculation.division(num1, num2)	   <<
		endl << endl;
	break;
	case 5:
		cout << "\n\n" << num1 << " r " << num2 << " = " << calculation.modulus(num1, num2)        <<
		endl << endl;
	break;
	}
}
Last edited on
what exactly are you getting that you think is incorrect?
eg are you adding 3+3 and getting 5.999999999999999999 or 6.00000000000000001 or something? or do you get like 27? Do you try each part independently (add a bunch of times, then re-run and multiply a bunch of times, etc?) or randomly? We need more info on what you are seeing and how you got it to find it quicker.

Hello MoreUmph,

This is an interesting program to work on. Even though I have not found the answer yet.

Some small points that will be useful in the future:

A long time ago I read something about the standard arrays being dangerous somehow

Just so you know you are using a C style array not a "std:array". There is a big difference. The "std::array" requires the header file "<array>" and would be defined as std::array <double, 1000> num{};. The empty {}s at the end initializes each element to zero the same as = {}. num{}; is just a shorter way of writing this.

Although there is nothing wrong with what you have done, and I will make more than one point here:
1
2
3
4
5
6
7
8
9
10
void off()
{
	//if (choice == 0)
	//{
	//	on = false;
	//}

	if (!choice)
		on = false;
}


The commented code is your original and the other is my revision. As you can see when the {}s line up in the same column it is easier to find the match. The extra white space makes no difference to the compiler.

The other point is with the if statement. When there is only one line the {}s are optional. The same is true for an else, for or while loop. Mostly it is less to worry about when writing.

This is kind of minor, but makes things easier to understand when something is displayed on the screen:
Your code:
1
2
cout << "\n\nEnter number\n" << endl;
cin  >> num[i];

To many "\n"s and "endl" before the "cin".

My revision with an added option:
1
2
3
4
5
6
7
8
9
cout << "\nEnter number: ";
cin >> num[fstOppIdx];

ui.display_operation();
cin >> choice;
off();

if (!on)
	return;


The point of lines 8 and 9 is to check if "on" has become false in which case there is no point to continue just return to main where the program will end.

For the program. I see little use for the class since all the functions are public and there are no private variables associated with the class. A regular function would work just as well. It mostly defeats the the purpose of using a class.

I do not see the use of the array or why it has to be there. Using the variables like "num1", "num2" and "result" will achieve the same results as the array. For the function "first_operation" you send the variables "num1" and "num2" to be calculated and store the answer in "result". For the "consecutive_operation" function you would send "result an "num2" to be calculated and store the answer in "result" ready for the next calculation. This makes the program easier to follow and to understand what is being sent to a function. Also this would help make it easier when sending variables to a function and when receiving variables by a function. Note the variables used in a function are local to that function, so the same names for variables can be used without a conflict, although there may still be a problem when there are variables in the global scope.

One thing I did notice in the two functions that follow main:

1
2
3
ui.display_operand(choice, num[fstOppIdx], num[secOppIdx]);

num[secOppIdx] = calculate.set_operand(choice, num[secOppIdx], num[fstOppIdx]);


I gave "i" and "j" new names. Notice on line 1 you are sending the array elements as "fstOppIdx" and "secOppIdx", but on line 3 they are being sent in reverse order. This may not be a problem for addition and multiplication, but it could be a big problem for the rest. Point 20 - 5 is not the same as 5 - 20. The same can be said for division.

The appearance is that somewhere something is being switched or reversed and I have not figured out where this is yet.

I have been considering making some big changes to the program to see if that makes any difference.

Eventually something will click and I will see some small thing I have been missing.

Hope that helps,

Andy
Registered users can post here. Sign in or register to post.