Whilst working on a personal project of mine, I came across a need to divide two very large arbitrary numbers (each number having roughly 100 digits).
So i wrote out the very basic code for division (i.e., answer = a/b, where a and b are imputed by the user)and quickly discovered that it only has a precision of 16 digits! It may be obvious at this point that Im not a coder!
So i searched the internet and found a code that, as far as i can tell, uses the traditional method of long division by making a string(but too be honest im not sure as im quite confused by it). But upon running the code it gives out some incorrect answers and wont work at all if a>b.
Im not even sure if there's a better way to solve this problem than the method in the code below!? Maybe there's a simpler code??
So basically i need help to write a code, in C++, to divide two very large numbers.
Any help or suggestions are greatly appreciated!
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std; //avoids having to use std:: with cout/cin
int main (int argc, char **argv)
{
string dividend, divisor, difference, a, b, s, tempstring = ""; // a and b used to store dividend and divisor.
int quotient, inta, intb, diff, tempint = 0;
char d;
quotient = 0;
cout << "Enter the dividend? "; //larger number (on top)
cin >> a;
cout << "Enter the divisor? "; //smaller number (on bottom)
cin >> b;
//making the strings the same length by adding 0's to the beggining of string.
while (a.length() < b.length()) a = '0'+a; // a has less digits than b add 0's
while (b.length() < a.length()) b = '0'+b; // b has less digits than a add 0's
inta = a[0]-'0'; // getting first digit in both strings
intb = b[0]-'0';
//if a<b print remainder out (a) and return 0
if (inta < intb)
{
cout << "Quotient: 0 " << endl << "Remainder: " << a << endl;
}
else
{
a = '0'+a;
b = '0'+b;
diff = intb;
//s = b;
// while ( s >= b )
do
{
for (int i = a.length()-1; i>=0; i--) // do subtraction until end of string
{
inta = a[i]-'0'; // converting ascii to int, used for munipulation
intb = b[i]-'0';
if (inta < intb) // borrow if needed
{
a[i-1]--; //borrow from next digit
a[i] += 10;
}
diff = a[i] - b[i];
char d = diff+'0';
s = d + s; //this + is appending two strings, not performing addition.
}
quotient++;
a = s;
// strcpy (a, s);
}
while (s >= b); // fails after dividing 3 x's
cout << "s string: " << s << endl;
cout << "a string: " << a << endl;
cout << "Quotient: " << quotient << endl;
//cout << "Remainder: " << s << endl;
}
system ("pause");
return 0;
cin.get(); // allows the user to enter variable without instantly ending the program
cin.get(); // allows the user to enter variable without instantly ending the program
}
There are much better methods than that. This subtractive method is arbitrarily slow for large dividends and small divisors. The canonical method is given as Algorithm D in Knuth, D.E., The Art of Computer Programming, volume 2, but I'm sure you will find it online. I'd be astonished if it wasn't in Wikipedia somewhere.
Related
The point of this exercise was to create code that can compute very large sums by using an algorithm close to how you would do it by hand. My code seems to work just fine, except for one specific test case, which is 9223372036854775808 + 486127654835486515383218192. I'm not sure what is special about this specific test case for it to fail, because the code is totally capable of carrying over, as well as adding numbers that have two different amounts of digits...Help would be greatly appreciated.
Edit: The output for this case is +'2+-0+*.4058858552237994000
// Basic mechanism:
//reverse both strings
//reversing the strings works because ex. 12+12 is the same as 21+21=42->reverse->24
//add digits one by one to the end of the smaller string
//dividing each sum by 10 and attaching the remainder to the end of the result-> gets us the carry over value
// reverse the result.
//ex. 45+45 ->reverse = 54+54 -> do the tens place -> 0->carry over -> 4+4+1 -> result= 09 -> reverse -> 90.
#include <iostream>
#include <cstring>
using namespace std;
string strA;
string strB;
string ResStr = ""; // empty result string for storing the result
int carry =0;
int sum; //intermediary sum
int n1; //length of string 1
int n2; // length of string 2
int rem; // remainder
int main()
{
cout << "enter" << endl;
cin >> strA;
cout << "enter" << endl; // I didn't know how to write this program to use argv[1] and argv[2] so this was my solution
cin >> strB;
// turning the length of each string into an integer
int n1 = strA.length(), n2 = strB.length();
if (n1<n2){
swap(strA,strB);
}//for this part I have no idea why this has to be the case but it only works if this statement is here
// Reversing both of the strings so that the ones, tens, etc. positions line up (the computer reads from left to right but we want it to read from right to left)
reverse(strA.begin(), strA.end());
reverse(strB.begin(), strB.end());
for (int i=0; i<n2; i++)//start at 0, perform this operation until the amount of times reaches the value of n2
{
//get the sum of current digits
int sum = ((strA[i]-'0')+(strB[i]-'0')+carry);
int quotient=(sum/10);
int rem=(sum-10*quotient);
ResStr+=(rem+'0'); //this gets the remainder and adds it to the next row
// Calculate carry for next step. Thus works because carry is an integer type, so it will truncate the quotient to an integer, which is what we want
carry = sum/10;
}
// Add the remaining digits of the larger number
for (int i=n2; i<n1; i++) //start at n1, perform this operation until the amount of times reaches the value of n1
{
int sum = ((strA[i]-'0')+carry);
int quotient=(sum/10);
int rem=(sum-10*quotient);
ResStr+=(rem+'0');
carry = sum/10;
}
// Add remaining carry over value
if (carry)
ResStr+=(carry+'0');
// reverse the resulting string back, because we reversed it at the beginning
reverse(ResStr.begin(), ResStr.end());
cout << "The result is " << ResStr << endl;
return 0;
}
After a lot of experimentation, what made the difference for me was replacing n1 and n2 entirely with strA.length() and strB.length() respectively in the for loop declarations. I'm not entirely sure why this happens, so if anyone has an explanation- please forward it.
Anyway, here's my version of the code:
//Basic mechanism: reverse both strings
//reversing the strings works because ex. 12+12 is the same as 21+21=42->reverse->24 (for single-digit sums smaller than 10)
//add digits one by one to the end of the smaller string
//dividing each sum by 10 and attaching the remainder to the end of the result-> gets us the carry over value reverse the result (mod 10 arithetic)
//ex. 45+45 ->reverse = 54+54 -> do the tens place -> 0->carry over -> 4+4+1 -> result= 09 -> reverse -> 90.
//ex. 90+90 ->reverse = 09+09 -> do the tens place -> 0->carry over ->0+ 9+9 ->carry over->1+ result= 081 -> reverse -> 180.
#include <iostream>
using std::cin; using std::cout;
#include <cstring>
using std::string;
#include <algorithm>
using std::reverse;
string strA, strB, ResStr = "";
int carry = 0, sum;
int main() {
//get user input
cout << "Enter first number: "; cin >> strA;
cout << "Enter second number: "; cin >> strB; cout << "\n";
if (length_strA < length_strB){ swap(strA,strB); } //force stringA to be larger (or equal) in size
//Reversing both of the strings so that the ones, tens, etc. positions line up (the computer reads from left to right but we want it to read from right to left)
reverse(strA.begin(), strA.end()); cout << strA << "\n";
reverse(strB.begin(), strB.end()); cout << strB << "\n";
for (int i = 0; i < strB.length(); i++) {
sum = int(strA[i])-48 + int(strB[i])-48 + carry/10;
ResStr += char(sum % 10)+48;
carry = sum - sum%10;
}
// Add the remaining digits of the larger number
//start at strB.length, perform this operation until the amount of times reaches the value of strA.length
for (int i = strB.length(); i < strA.length(); i++) {
sum = int(strA[i])-48 + carry/10;;
ResStr += char(sum % 10)+48;
carry = sum - sum%10;
}
// Add remaining carry over value
if (carry != 0) { ResStr += char(carry)+48; }
// reverse the resulting string back, because we reversed it at the beginning
reverse(ResStr.begin(), ResStr.end());
//return user result
cout << "The result is: " << ResStr << "\n";
return 0; }
To answer why, it's because even once strB ended, it kept iterating through making a new sum in the first loop until strA ended. This meant it was reading null values for strB[i] and adding that to strA[i]+carry- which effectively shifted all the characters into the noisy-looking mess it was.
I'm writing a C++ program that converts a decimal number to binary and hexadecimal.
The problem is that for some reason it concatenates the number "1875954912" to both representations every time.
I've tried a bunch of things - mainly changing up how the program calculates numArrayLength and the for-loop in my decToBase function, but I haven't been able to figure out why this happens yet.
The program is not complete by the way - it doesn't turn integers bigger than 9 into letters for the hex representation yet, but that's not my main concern right now.
Here is my code:
#include <iostream>
#include <cmath>
using namespace std;
int howManyBitsNeeded(int someNum, int base) {
int numOfDivisions = 0;
while (someNum != 0) {
someNum = floor(someNum / base);
numOfDivisions += 1;
}
return numOfDivisions;
}
int decToBase(int someNum, int base) {
int bitsNeeded = howManyBitsNeeded(someNum,base);
int numArrayLength = bitsNeeded;
int numArray[bitsNeeded];
while (bitsNeeded > 0) {
numArray[bitsNeeded] = (someNum % base);
someNum = floor(someNum / base);
bitsNeeded -= 1;
}
for (int k = (numArrayLength-1); k >= 0; --k) {
cout << numArray[(numArrayLength - k)];
}
}
int main() {
int inpNum;
cout << "Enter your number: ";
cin >> inpNum;
cout << "Binary representation: " << decToBase(inpNum,2) << endl;
cout << "Hexadecimal representation: " << decToBase(inpNum,16);
return 0;
}
And here's what the output looks like:
Enter your number: 25
Binary representation: 110011875954912
Hexadecimal representation: 191875954912
Any help would be greatly appreciated!
Your decToBase is declared as returning an int, but it doesn't actually return anything. Your compiler should warn you about this. Since you're not returning anything here, change its return type to void. Then instead of trying to print its return value, simply call the function without printing it:
std::cout << "Binary representation: ";
decToBase(inpNum, 2); // this already prints the number, no need to pass it to std::cout
std::cout << endl;
std::cout << "Hexadecimal representation: ";
decToBase(inpNum, 16);
std::cout << std::endl;
Or of course you can change the function to return the string that you want to print instead of printing it inside the function.
Also, there's an issue here:
int numArray[bitsNeeded];
This is out of range when you try to access it here:
while (bitsNeeded > 0) {
numArray[bitsNeeded] = (someNum % base);
And also later when you try to print it. To get rid of this off by one error, you have to change this to
numArray[bitsNeeded-1] = (someNum % base);
And in the output change it to
cout << numArray[(numArrayLength - k -1)];
And while you're at it, instead of having it as a VLA (which isn't part of C++ and only works if the compiler tolerates it), I would recommend a vector:
std::vector<int> numArray(bitsNeeded+1); // include <vector> for this to work
Furthermore, note that integer division is already truncated, so unless you plan to support negative numbers later on, you can silence a warning about implicit double to int conversion by changing this:
someNum = floor(someNum / base);
To this:
someNum /= base;
So, I was bored, and decided to make something completely random, then I came across the collatz conjecture: start with any positive number, and if it is even, devide by two. If it is odd, multiply by three and add one. When repeating this, you will end at the number one. So I made this code:
//Collatz Conjecture by Lucas Knook
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
long long n;
cin >> n;
cout << setw(5) << n;
while(true){
if(n % 2 == 0 && n != 1){
//is even
cout << " E" << endl;
n /=2;
cout << setw(5) << n;
}
else if(n != 1){
//is odd
cout << " O" << endl;
n = n * 3 + 1;
cout << setw(5) << n;
}
else break;
}
cout << " O" << endl << endl << "end loop";
return 0;
}
I am still learning c++ (I just completed the sololearn course, and I am about to get the "C++ for dummies all-in-one" book), but I think this is a good start for me, and it works.
There is just one little problem: If I use big numbers, it does stop at one, and gets the odd and even right, but...
Look at this first part of the output when entering
"1000000000000000000000000" :
9223372036854775807 O
9223372036854775806 E
4611686018427387903 O
-4611686018427387906 E
-2305843009213693953 O
-6917529027641081858 E
-3458764513820540929 O
8070450532247928830 E
4035225266123964415 O
-6341068275337658370 E
-3170534137668829185 O
8935141660703064062 E
4467570830351532031 O
-5044031582654955522 E
-2522015791327477761 O
-7566047373982433282 E
-3783023686991216641 O
7097673012735901694 E
3548836506367950847 O
-7800234554605699074 E
Ehm, that's a bit weird, isn't it? (don't look at the line breaks, it is perfectly stacked, it just doesn't show here, because I copied the output)
Can someone please explain me why this is happening and how to fix it?
You've exceeded the limits of long long integer values. The first value in your output is truncated to be much smaller than your input, then when you get to 4611686018427387903 it's multiplied by 3, since it isn't even. That's when it overflows the type and wraps around into negative values. You'll need to use a BigInteger library, like TTMath.
Basically as other people pointed out you don't check for overflow. But I would like to point out different thing, your code is still not valid as you don't check if you got into endless loop, when multiplication and division sequence generates the same numbers, your while will never end.
This is correct code with simple overflow detection:
#include <iostream>
#include <unordered_set>
bool colatazConjecture(int n) {
std::unordered_set<int> localComputed;
int newN = 0;
while (n != 1) {
if (!localComputed.emplace(n).second) {
throw "Cycle detected";
}
newN = n;
if (n & 0x1) {
newN = 3*n + 1;
if (newN <= n) {
throw std::overflow_error("Overflow for " + std::to_string(newN));
}
} else {
newN >>= 1;
}
n = newN;
}
}
In C++, I want to print the first n prime numbers (for this example let's assume n=1000).
In order to do this, I've found mpz_nextprime from the GMP library.
I'd assume you use it like this
int n = 2;
for(int i = 0; i < 1000; i++) {
n = mpz_nextprime(n);
cout << n << endl;
}
but this doesnt compile as mpz_nextprime takes two mpz_t arguments.
How can you use mpz_nextprime in this context?
The reason for mpz_nextprime using mpz_t instead of normal integer types like int or long is that after a certain point the prime numbers will be too large to be representable in a int or long.
Here's a snippet of code to print all up to the 1000th prime number:
#include <gmp.h>
int main() {
mpz_t n;
mpz_init(n);
mpz_set_ui(n, 2);
for (size_t i = 0; i < 1000; i++) { // first 1000 primes
mpz_nextprime(n, n);
cout << "The " << (i + 1) << "th " << " prime is " << mpz_get_ui(n) << endl;
}
}
Note that this code will only work up to a certain prime number because in order to print it, we convert it to an unsigned int using mpz_get_ui here.
If you want to print larger prime numbers, use mpz_get_str (but don't forget to free() the string if you use NULL as first parameter).
So, I hate to ask, but, I'm having some issue with this, I'm new to C++ and I'm just starting out. Everything is done for the most part. Expect for a little thing.
Line 35-36 should be calculating the average (Which for some reason, I haven't been able to get it to work.)
Line 41-47 should print out the percentage that heads/tails was landed on with precision to one decimal, and then print out the correct numbers of * to represent the percentage.
But, when I run it, my heads/tail count is messed up. As well as my percentage numbers. I'm just looking for a push in the right direction.
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <iomanip>
using std::cout; using std::cin; using std::endl;
using std::fixed; using std::setprecision;
int main()
{
srand(time(0));
int userInput,
toss,
headsCount,
tailsCount;
double headsPercent = 0,
tailsPercent = 0;
cout << "How many times do you want to toss the coin? ";
cin >> userInput;
while(userInput < 0)
{
cout << "Please enter a positive number: ";
cin >> userInput;
}
for(int i = 1; i < userInput; i++)
{
toss = rand() % 2;
if(toss == 0)
headsCount++;
else
tailsCount++;
}
headsPercent = userInput / headsCount * 100;
tailsPercent = userInput / tailsCount;
cout << "Heads: " << headsCount << endl
<< "Tails: " << tailsCount << endl << endl;
cout << "Heads Percentage: " << fixed << setprecision(1) << headsPercent << " ";
for(int b = 0; b < headsPercent; b++)
cout << "*";
cout << "\nTails Percentage: " << tailsPercent << " ";
for(int b = 0; b < tailsPercent; b++)
cout << "*";
return 0;
}
In addition to the uninitialized variables here, that others have pointed out, the calculations are all wrong.
Take out paper and pencil, and run some your own calculations the old-fashioned way.
Let's say there were five tosses, three heads, two tails. This means that (after fixing the uninitialized variables):
userInput=5
headsCount=3
tailsCount=2
Now, here's how you're calculating your supposed percentages:
headsPercent = userInput / headsCount * 100;
tailsPercent = userInput / tailsCount;
So, using your own numbers, you will get:
headsPercent = 5 / 3 * 100
tailsPercent = 5 / 2;
Does this look right to you? Of course not. You can do the arithmetic yourself. Divide 5 by 3 and multiply by 100. This is integer division, so five divided by three is 1, multiplied by 100 is 100. Five divided by two is two. So you get 100% and 2% here.
Of course, that's wrong. Two and three times, out of five, is 40% and 60%, respectively.
Writing a program means:
A) Figure out how calculations need to be made
B) Write the code to do the calculations.
You're still on step A. You need to figure out how you want to make these calculations so they're correct, first.
This has nothing really to do with C++. If you were using any other language, and coded this, in that manner, you'll get the same wrong answers.
The only thing this might have to do with C++ is that integer division, in C++ does not produce a fractional amount. It's integer division. But that's not your only problem.
Firstly u have to correct ur basics of mathematics.
Calculating %age means
example
(Marks obtained)/(Total marks)*100
Not (Total marks/marks obt)*100
Dividing any no by 0 is not defined. So if ur current code randomly assign toss or head =0, then obviously u will have errors.
Secondly talking about codes, U should either initialize i from 0 , or u should use
for (i=1; i<=userInput; i++)
As otherwise the head+toss value will be userInput-1.
Also remember to initialise variables like
Int headsCount=0;
etc. As the variable will take any random value if not initialised to a fixed no. (Though it does not creates a problem here)
And just change the datatype
int userInput,
toss,
headsCount,
tailsCount;
To
double userInput,
toss,
headsCount,
tailsCount;
This will solve your problem.
Advice: Please use
using namespace std;
in the starting of ur programs as u have to type a lot of std::
Welcome to C++. You need to initialise your variables. Your compiler should have warned you that you were using a variable without initialising it. When you don't initialise a value, your program has undefined behaviour.
I'm talking about headsCount and tailsCount. Something like this should be fine:
int headsCount = 0, tailsCount = 0;
Also note that your loop should start at 0, not 1, since you are using the < operator on the final condition.
Finally, your percentage calculations are backwards. It should be:
headsPercent = headsCount * 100 / userInput;
tailsPercent = tailsCount * 100 / userInput;
Now, there's a weird thing that might happen because you are using integer division. That is, your percentages might not add up to 100. What's happening here is integer truncation. Note that I dealt with some of this implicitly using the 100x scale first.
Or, since the percentages themselves are double, you can force the calculation to be double by casting one of the operands, thus avoiding integer truncation:
headsPercent = static_cast<double>(headsCount) / userInput * 100;
In fact, since the only two possibilities are heads and tails, you only need to count one of them. Then you can do:
tailsPercent = 100 - headsPercent;
1) This loop should start from 0:
for(int i = 1; i < userInput; i++)
2) The divisions are not correct:
//headsPercent = userInput / headsCount * 100;
//tailsPercent = userInput / tailsCount;
headsPercent = headsCount / userInput * 100;
tailsPercent = tailsCount / userInput * 100;
3) Finally:
cout << "\nTails Percentage: " << fixed << setprecision(1) << tailsPercent << " ";