A program takes two long fractions, and performs addition, subtraction, multiplication and comparison operations on them. In the standard CLion compiler (MinGW) the code is executed correctly, but in order to check it you need to pass the code in a compiler where the multiplication method (Prouz) does not work correctly.
MinGW:
input:
698768322001934555.698489123321899
0.347657908264796
output:
698768322001934556.046147031586695
698768322001934555.350831215057103
242932333188893996.179870469985582542826437567604
greater
Visual C++ 2013:
input:
698768322001934555.698489123321899
0.347657908264796
output:
698768322001934556.046147031586695
698768322001934555.350831215057103
24293233318889066-379-766-1096-1463-1510-1242.-906-653-28680-187-204-449-707-851
-632-774-1078-1248-1204-1452-1646-1308-975-980-715-362-347-698-1073-1421-1323-127
4-882-441
greater
What could be the problem and what is the best way to fix it?
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
class Fraction
{
private:
int a, b;
char* after;
char* before;
public:
Fraction()
{
a = 0, b = 0;
char* before = new char[b + 1];
char* after = new char[a + 1];
}
char Read()
{
for (int i = 0; i < 20; i++)
{
char h;
cin >> h;
if ((h != '.')||(h=='0'))
{
before = AddStruct(before, b);
before[i] = h;
b++;
}
else
break;
}
for (int i = 0; i < 20; i++)
{
char h;
h = cin.get();
if (isspace(h))
{
break;
}
else
{
after = AddStruct(after, a);
after[i] = h;
a++;
}
}
return before[b], after[a];
}
char* AddStruct(char* after, const int a)
{
if (a == 0)
after = new char[a + 1];
else
{
char* tempnumber = new char[a + 1];
for (int i = 0; i < a; i++)
tempnumber[i] = after[i];
delete[] after;
after = tempnumber;
}
return after;
}
int Plus(Fraction chislo1, Fraction chislo2)
{
int ostatok = 0;
int* summaafter = new int[chislo1.a];
int* summabefore = new int[chislo1.b];
int ost = 0;
for (int i = (a - 1); i >= 0; i--)
{
const char h1 = chislo1.after[i];
int sum1 = static_cast<int>(h1) - 48;
const char h2 = chislo2.after[i];
int sum2 = static_cast<int>(h2) - 48;
int summa = sum1 + sum2 + ostatok;
ostatok = 0;
if (summa > 9)
{
summa -= 10;
ostatok++;
}
summaafter[i] = summa;
ost = ostatok;
}
if (chislo2.before[0] == '0')
for (int i = (chislo1.b - 1); i >= 0; i--)
{
summabefore[i] = static_cast<int>(chislo1.before[i])-48;
if (i == (chislo1.b - 1))
summabefore[i] += ost;
}
else
{
for (int i = (b - 1); i >= 0; i--)
{
const char h1 = chislo1.before[i];
int sum1 = static_cast<int>(h1) - 48;
const char h2 = chislo2.before[i];
int sum2 = static_cast<int>(h2) - 48;
int summa = sum1 + sum2 + ostatok;
ostatok = 0;
if (summa > 9)
{
summa -= 10;
ostatok++;
}
summabefore[i] = summa;
}
}
for (int i = 0; i < b; i++)
{
cout << summabefore[i];
}
cout << ".";
for (int i = 0; i < a; i++)
{
cout << summaafter[i];
}
cout << endl;
return summaafter[a], summabefore[b];
}
int Minus(Fraction chislo1, Fraction chislo2)
{
int proverka = 0;
if (chislo1.before[0] < chislo2.before[0])
proverka = 1;
int ostatok = 0;
int* minusafter = new int[chislo1.a];
int* minusbefore = new int[chislo1.b];
int ost = 0;
for (int i = (a - 1); i >= 0; i--)
{
const char h1 = chislo1.after[i];
int min1 = static_cast<int>(h1) - 48;
const char h2 = chislo2.after[i];
int min2 = static_cast<int>(h2) - 48;
if (proverka == 1)
{
int kk = min1;
min1 = min2;
min2 = kk;
}
int minus = min1 - min2 + ostatok;
ostatok = 0;
if (minus < 0)
{
minus += 10;
ostatok--;
}
minusafter[i] = minus;
ost = ostatok;
}
if (chislo2.before[0] == '0')
{
for (int i = (chislo1.b - 1); i >= 0; i--)
{
minusbefore[i] = static_cast<int>(chislo1.before[i]) - 48;
if (i == (chislo1.b - 1))
minusbefore[i] += ost;
}
}
else
{
for (int i = (b - 1); i >= 0; i--)
{
const char h1 = chislo1.before[i];
int min1 = static_cast<int>(h1) - 48;
const char h2 = chislo2.before[i];
int min2 = static_cast<int>(h2) - 48;
if (proverka == 1)
{
int kk = min1;
min1 = min2;
min2 = kk;
}
int minus = min1 - min2 + ostatok;
ostatok = 0;
if (minus < 0)
{
minus += 10;
ostatok--;
}
minusbefore[i] = minus;
}
}
if (proverka == 1)
cout << "-";
for (int i = 0; i < b; i++)
{
cout << minusbefore[i];
}
cout << ".";
for (int i = 0; i < a; i++)
{
cout << minusafter[i];
}
cout << endl;
return minusafter[a], minusbefore[b];
}
int Prouz(Fraction chislo1, Fraction chislo2)
{
int ostatok = 0;
int* prouz1 = new int[chislo1.a + chislo1.b];
int* prouz2 = new int[chislo2.a + chislo2.b];
int* prouzsum = new int[(chislo1.a + chislo1.b) * 2 + 3];
for (int i = 0; i < chislo1.b; i++)
{
prouz1[i] = static_cast<int>(chislo1.before[i]) - 48;
}
int n = 0;
for (int i = chislo1.b; i < (chislo1.a + chislo1.b); i++)
{
prouz1[i] = static_cast<int>(chislo1.after[n]) - 48;
n++;
if (n >= chislo1.a)
break;
}
for (int i = 0; i < chislo2.b; i++)
{
prouz2[i] = static_cast<int>(chislo2.before[i]) - 48;
}
n = 0;
for (int i = chislo2.b; i < (chislo2.a + chislo2.b); i++)
{
prouz2[i] = static_cast<int>(chislo2.after[n]) - 48;
n++;
if (n >= chislo2.a)
break;
}
int k = (chislo1.a + chislo1.b) * 2; int t = 0;
for (int k1 = 0; k1 < (k); k1++)
{
prouzsum[k1] = 0;
}
for (int i = ((chislo2.a + chislo2.b) - 1); i >= 0; i--)
{
for (int j = ((chislo1.a + chislo1.b) - 1); j >= 0; j--)
{
prouzsum[k - t - 1] += prouz2[i] * prouz1[j] + ostatok;
ostatok = 0;
while (prouzsum[k - t - 1] > 9)
{
prouzsum[k - t - 1] -= 10;
ostatok++;
}
k--;
if (j == 0)
prouzsum[k - t - 1] += ostatok;
}
ostatok = 0;
t++;
k = (chislo1.a + chislo1.b) * 2;
}
int prpr = 0;
for (int i = 0; i < ((chislo1.a + chislo1.b) * 2); i++)
{
if (prouzsum[i] != 0)
{
prpr++;
if (i == ((chislo1.b) * 2))
cout << ".";
cout << prouzsum[i];
}
else
{
if (prpr != 0)
cout << prouzsum[i];
}
}
delete[] prouz1;
delete[] prouz2;
delete[] prouzsum;
return 0;
}
void Srav(Fraction chislo1, Fraction chislo2)
{
cout << endl;
if (chislo1.before[0] > chislo2.before[0])
{
cout << "greater";
}
else
{
if (chislo1.before[0] < chislo2.before[0])
cout << "less";
else
cout << "equal";
}
}
};
int main()
{
Fraction chislo1, chislo2;
chislo1.Read(); chislo2.Read();
chislo1.Plus(chislo1, chislo2);
chislo1.Minus(chislo1, chislo2);
chislo1.Prouz(chislo1, chislo2);
chislo1.Srav(chislo1, chislo2);
return 0;
}
How the Prouz method works: First, the method converts each long fraction into an array of integers, where each digit is stored in a separate array element. Then it creates three arrays: prouz1, prouz2, and prouzsum. Prouz1 and prouz2 are arrays that store the digits of the first and second long fraction, respectively. Prouzsum is the array that will store the result of multiplication.
The method then performs the multiplication itself by multiplying each digit of the first long fraction with all digits of the second long fraction, starting with the last and ending with the first. The multiplication results are added to the prouzsum array using the carry method.
Finally, the method outputs the result of the multiplication, which is stored in the prouzsum array, converting the array back to a long fraction. At the end, the method frees the memory allocated to the arrays.
I tried to rewrite the method using vectors, but nothing really changed, everything worked correctly on me as usual, and on visual 2013, the output remained the same
void Prouz(Fraction chislo1, Fraction chislo2)
{
vector<int> prouz1(chislo1.a + chislo1.b);
vector<int> prouz2(chislo2.a + chislo2.b);
vector<int> prouzsum((chislo1.a + chislo1.b) * 2 + 3);
for (int i = 0; i < chislo1.b; i++)
{
prouz1[i] = static_cast<int>(chislo1.before[i]) - 48;
}
int n = 0;
for (int i = chislo1.b; i < (chislo1.a + chislo1.b); i++)
{
prouz1[i] = static_cast<int>(chislo1.after[n]) - 48;
n++;
if (n >= chislo1.a)
break;
}
for (int i = 0; i < chislo2.b; i++)
{
prouz2[i] = static_cast<int>(chislo2.before[i]) - 48;
}
n = 0;
for (int i = chislo2.b; i < (chislo2.a + chislo2.b); i++)
{
prouz2[i] = static_cast<int>(chislo2.after[n]) - 48;
n++;
if (n >= chislo2.a)
break;
}
int k = (chislo1.a + chislo1.b) * 2; int t = 0;
for (int k1 = 0; k1 < (k); k1++)
{
prouzsum[k1] = 0;
}
int ostatok = 0;
for (int i = ((chislo2.a + chislo2.b) - 1); i >= 0; i--)
{
for (int j = ((chislo1.a + chislo1.b) - 1); j >= 0; j--)
{
prouzsum[k - t - 1] += prouz2[i] * prouz1[j] + ostatok;
ostatok = 0;
while (prouzsum[k - t - 1] > 9)
{
prouzsum[k - t - 1] -= 10;
ostatok++;
}
k--;
if (j == 0)
prouzsum[k - t - 1] += ostatok;
}
ostatok = 0;
t++;
k = (chislo1.a + chislo1.b) * 2;
}
int prpr = 0;
for (int i = 0; i < ((chislo1.a + chislo1.b) * 2); i++)
{
if (prouzsum[i] != 0)
{
prpr++;
if (i == ((chislo1.b) * 2))
cout << ".";
cout << prouzsum[i];
}
else
{
if (prpr != 0)
cout << prouzsum[i];
}
}
}
input.get()
returns eof if there are no more characters available. As your second number is at the end of input, if it is less than 20 characters and there is no trailing space you keep reading into the eof appending the eof value cast to a character into your array. Adding a space to the end of your input makes it work: https://godbolt.org/z/bY6zb5M9n. You should never use a value read from a stream without checking that the read was successful, the minimum change is to add a check for eof:
int h;
h = cin.get();
if (std::char_traits<char>::eof() == h || isspace(h))
{
break;
}
Your code still has many issues with memory leaks and accessing out of the bounds of the arrays. It'd be much simpler to use std::string
, for example your Read function could just be:
std::getline(cin, before, '.');
std::getline(cin, after);
where before
and after
are std::string
member variables, the members a
and b
can be replaced with before.size()
and after.size()
. e.g.: https://godbolt.org/z/onvY4154j