Recently I started learning c++ and I had an idea to make a calculator, that can take any imaginable number and I wrote this code:
#include <iostream>
#include <string>
#include <vector>
// Advanced calculator by xxnoflz;
// This calculator works best with summation, subtraction and multiplication
// and can work with numbers with ricilous amout of digits;
// But division and modulo works worse because of principle how division works;
void pause() {
std::cout << '\n' << "Press <Enter> to continue...";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
//std::cin.get(); // Use when not debug
} // PAUSE
int find_first_digit(std::vector<int>& vctr) {
int iter{ int(vctr.size())-1 }; // Get the position of last number of array
while (vctr[iter] == 0 && iter > 0) { --iter; } // Iterate while numbers are zeroes
return iter;
} // Function to find and return the position of the first digit that is not zero
std::vector<int> operator+(std::vector<int>& first, std::vector<int>& second) {
int f1{ find_first_digit(first) }; // Position of first digit of first num
int f2{ find_first_digit(second) }; // Position of first digit of second num
int first_digit_pos{ (f1 > f2) ? f1 : f2 }; // Get the largest number first position
for (int iter{}; iter <= first_digit_pos; ++iter) { // Don't need to iterate through zeroes, just the numbers that matter
first[iter] += second[iter];
if (first[iter] >= 10) { // Overflow control
first[iter] -= 10;
first[iter + 1]++;
}
}
return first;
}
std::vector<int> operator-(std::vector<int>& first, std::vector<int>& second) {
bool negative{ false }; // Bool for negative check
int size{ int(first.size()) };
int f1{ find_first_digit( first ) }; // Position of first digit of first num
int f2{ find_first_digit( second )}; // Position of first digit of second num
int check{(f1 > f2) ? f1 : f2}; // Get the largest number first position
if (first[check] < second[check]) { std::swap(first, second); negative = true; } // If the first num is smaller the second then result is negative
for (int iter{}; iter <= check; ++iter) { // Don't need to iterate through zeroes, just the numbers that matter
if (first[iter] - second[iter] < 0) {
first[iter] += 10;
first[iter+1]--;
}
first[iter] -= second[iter];
}
if (negative) { first[find_first_digit(first)] *= -1; } // Add to the first significant digit negative sign if number should be negative
return first;
}
std::vector<int> operator*(std::vector<int>& first, std::vector<int>& second) {
int size{ int(first.size()) };
int f1{ find_first_digit(first) }; // Position of first digit of first num
int f2{ find_first_digit(second) }; // Position of first digit of second num
std::vector<int> result(size); // Create a vector to store answer in it
for (int second_it{}; second_it <= f2; ++second_it) { // First: iterate through the second number to last significant digit
int pos{ second_it }; // Create an integer with first position to add answer to
for (int first_it{}; first_it <= f1 && pos < size; ++first_it, ++pos) { // Second: iterate through the first number to last significant digit
result[pos] += first[first_it] * second[second_it]; // And add the multiply of first and second digit to result with start position
if (result[pos] >= 10) { // Overflow control
result[pos + 1] += result[pos] / 10;
result[pos] %= 10;
}
}
}
return result;
}
std::vector<int> operator/(std::vector<int>& first, std::vector<int>& second) {
std::vector<int> result(first.size());
bool stop{ true }; // Check to continue the subtraction or not
while (stop) {
first = first - second; // Subtract the second number from first
stop = false;
for (int digit : first) { if (digit > 0) { stop = true; } if (digit < 0) { return result; } } // If even one digit is positive then continue, but if one is negative return the
result[0]++; // answer, and if all digits are zeroes then add 1 to answer and then return
for (int iter{}; iter < result.size(); ++iter) { //Overflow control with check of every digit
if (result[iter] >= 10) {
result[iter] -= 10;
result[iter+1]++;
}
}
}
return result;
}
std::vector<int> operator%(std::vector<int>& first, std::vector<int>& second) {
std::vector<int> check{ second }; std::vector<int> zero{0}; // Interesting feature here that I noticed is that when number evenly divides by another the second number
first = first / second; // stays unchanged, but when there is remainder it is stored in the second number. Pretty neat, huh!
return (second == check) ? zero : second; // All we need to do here is compare the values of second number, when unchanged return zeroes but when changed
} // return the second number.
int main() {
int extra_carry{ 10 }; // If some error happens it can be that amount of extra carry is insufficient
std::string input{};
std::getline(std::cin,input); // Get input
std::string nums{ "0123456789" };
std::string first_num{ input.begin(),input.begin() + input.find_first_not_of(nums)};
std::string second_num{ input.begin() + input.find_first_of(nums,input.find_first_not_of(nums)), input.end() };
char oprt{input[input.find_first_of("+-*/%")]};
int size{ int((first_num.size() > second_num.size()) ? first_num.size() : second_num.size()) + extra_carry }; // Parse input into first and second numbers and operator
std::vector<int> first(size);
std::vector<int> second(size);
std::reverse(first_num.begin(),first_num.end()); std::reverse(second_num.begin(), second_num.end()); // Reverse in order to do calculations
for (int it{}; it < first_num.length(); ++it) { first[it] = first_num[it] - '0'; }
for (int it{}; it < second_num.length(); ++it) {second[it] = second_num[it] - '0'; } // Convert string to vector to do the calculations
std::vector<int> result(size);
switch (oprt) {
case '+':
result = first+second;
break;
case '-':
result = first-second;
break;
case '*':
result = first*second;
break;
case '/':
result = first/second;
break;
case '%':
result = first%second;
break;
default:
std::cout << "Uknown operator!\n";
break;
}
int start{ find_first_digit(result) }; // Find the first digit of result
for (; start >= 0; --start) {
std::cout << result[start];
} // Print in reverse
pause();
return 0;
}
I know it's a little big, but I will take any suggestions to improve this code, thanks!
PS: The the divide and modulo function works slow
main()
to figure that out :) \$\endgroup\${ }
to initialize variables seems a little unconventional... \$\endgroup\${ }
is universal and better, but he still likes to use=
for simple types with simple values because he's used to it. A while back I made a post (I don't remember where I'm afraid) where I showed his slide and asked if we're ready to re-evaluate that style yet and use{ }
more. I would not fault him for using it consistently, and this is indeed taught to newcomers who don't have that old inertia. (The spacing is weird and hurts readability, though.) \$\endgroup\$