将大数字乘以字符串 - 一切正常,除非数字中有 9
Multiplying large numbers as strings - everything fine unless there is a 9 in the numbers
我不得不在 C++ 中创建一个 class - BigInteger - 它适用于以字符串形式编写的非常大的数字。作为作业的一部分,我还必须预定义乘法,这就是我所做的:
BigInteger& BigInteger::operator*(const BigInteger& rhs)
{
string tmp(num.length() + rhs.num.length(), '0');
//a string in which I'll be temporarily storing the result
char carry = '0';
int d = 0;
//I'll use this to move with one index to the left in the result
for (int i = num.length() - 1; i >= 0; --i)
//start with the multiplying from the end of the first number
{
carry = '0';
for (int j = rhs.num.length() - 1, z = tmp.length() - 1 - d; j >= 0; --j, --z)
//start with the multiplying from the end of the second number and begin filling the result string (again from the end)
{
tmp[z] = ((tmp[z] - '0') + (num[i] - '0') * (rhs.num[j] - '0') + (carry - '0')) + '0';
//basically add to the current number in the result the multiplication of the respective digits in the two original numbers, plus the carry from the previous mutiplication
carry = ((tmp[z] - '0') / 10) + '0';
tmp[z] = ((tmp[z] - '0') % 10) + '0';
if (j == 0 && carry != '0')
{
tmp[z - 1] = carry;
}
}
++d;
}
if (carry != '0')
{
tmp[0] = carry;
}
else
{
tmp.erase(0, 1);
}
num = tmp;
return *this;
}
即使是像 123456788*887654321 这样的大数字,一切都很好,但是一旦我尝试将其中包含 9 的数字相乘(包括较小的数字,如 6789*9876),不仅中间数字不对,而且还有差异在 6789*9876 和 9876*6789 之间,包括“+”和撇号等符号,在后一种情况下大致出现在中心。
这里有没有人遇到过这样的问题或者知道是什么原因造成的?
编辑:
这是预定义的 << 运算符:
ostream& operator<<(ostream& out, const BigInteger& rhs)
{
out << rhs.num;
return out;
}
和我的 "main":
#include "BigInteger.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
BigInteger num3("123456788");
BigInteger num4("887654321");
cout << num3 * num4 << endl;
//cout << num4 * num3 << endl;
}
和我的 class:
#ifndef H_BIGINTEGER
#define H_BIGINTEGER
#include <iostream>
#include <string>
using namespace std;
//I know I shouldn't have defined a namespace in the headers file, but left it for brevity's sake
class BigInteger
{
friend ostream& operator<<(ostream&, const BigInteger&);
public:
BigInteger();
BigInteger(string);
~BigInteger();
BigInteger(const BigInteger&);
BigInteger& operator=(const BigInteger&);
BigInteger& operator+(BigInteger&);
BigInteger& operator-(BigInteger&);
BigInteger& operator*(const BigInteger&);
private:
string num;
};
我使用的构造函数只是:
BigInteger::BigInteger(string num)
:num(num)
{}
std::string
char
已签名,当您添加 '0'
并稍后将其用于 carry
和 tmp[z]
时它会变为负数,因此它更好将其存储在临时 ìnt
6789*9876
---------
int(char(res + '0'))
-------------------------------
0+9*6+0=54 102
0+9*7+5=68 116
0+9*8+6=78 126
0+9*9+7=88 -120
8+8*6+0=56 104
8+8*7+5=69 117
8+8*8+6=78 126
8+8*9+7=87 -121
9+7*6+0=51 99
8+7*7+5=62 110
7+7*8+6=69 117
8+7*9+6=77 125
2+6*6+0=38 86
9+6*7+3=54 102
7+6*8+5=60 108
7+6*9+6=67 115
因此您可以像这样更改代码:
int res = ((tmp[z] - '0') + (num[i] - '0') * (rhs.num[j] - '0') + (carry - '0'));
carry = (res / 10) + '0';
tmp[z] = (res % 10) + '0';
if (j == 0)
{
tmp[z - 1] = carry;
}
我不得不在 C++ 中创建一个 class - BigInteger - 它适用于以字符串形式编写的非常大的数字。作为作业的一部分,我还必须预定义乘法,这就是我所做的:
BigInteger& BigInteger::operator*(const BigInteger& rhs)
{
string tmp(num.length() + rhs.num.length(), '0');
//a string in which I'll be temporarily storing the result
char carry = '0';
int d = 0;
//I'll use this to move with one index to the left in the result
for (int i = num.length() - 1; i >= 0; --i)
//start with the multiplying from the end of the first number
{
carry = '0';
for (int j = rhs.num.length() - 1, z = tmp.length() - 1 - d; j >= 0; --j, --z)
//start with the multiplying from the end of the second number and begin filling the result string (again from the end)
{
tmp[z] = ((tmp[z] - '0') + (num[i] - '0') * (rhs.num[j] - '0') + (carry - '0')) + '0';
//basically add to the current number in the result the multiplication of the respective digits in the two original numbers, plus the carry from the previous mutiplication
carry = ((tmp[z] - '0') / 10) + '0';
tmp[z] = ((tmp[z] - '0') % 10) + '0';
if (j == 0 && carry != '0')
{
tmp[z - 1] = carry;
}
}
++d;
}
if (carry != '0')
{
tmp[0] = carry;
}
else
{
tmp.erase(0, 1);
}
num = tmp;
return *this;
}
即使是像 123456788*887654321 这样的大数字,一切都很好,但是一旦我尝试将其中包含 9 的数字相乘(包括较小的数字,如 6789*9876),不仅中间数字不对,而且还有差异在 6789*9876 和 9876*6789 之间,包括“+”和撇号等符号,在后一种情况下大致出现在中心。
这里有没有人遇到过这样的问题或者知道是什么原因造成的?
编辑: 这是预定义的 << 运算符:
ostream& operator<<(ostream& out, const BigInteger& rhs)
{
out << rhs.num;
return out;
}
和我的 "main":
#include "BigInteger.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
BigInteger num3("123456788");
BigInteger num4("887654321");
cout << num3 * num4 << endl;
//cout << num4 * num3 << endl;
}
和我的 class:
#ifndef H_BIGINTEGER
#define H_BIGINTEGER
#include <iostream>
#include <string>
using namespace std;
//I know I shouldn't have defined a namespace in the headers file, but left it for brevity's sake
class BigInteger
{
friend ostream& operator<<(ostream&, const BigInteger&);
public:
BigInteger();
BigInteger(string);
~BigInteger();
BigInteger(const BigInteger&);
BigInteger& operator=(const BigInteger&);
BigInteger& operator+(BigInteger&);
BigInteger& operator-(BigInteger&);
BigInteger& operator*(const BigInteger&);
private:
string num;
};
我使用的构造函数只是:
BigInteger::BigInteger(string num)
:num(num)
{}
std::string
char
已签名,当您添加 '0'
并稍后将其用于 carry
和 tmp[z]
时它会变为负数,因此它更好将其存储在临时 ìnt
6789*9876
---------
int(char(res + '0'))
-------------------------------
0+9*6+0=54 102
0+9*7+5=68 116
0+9*8+6=78 126
0+9*9+7=88 -120
8+8*6+0=56 104
8+8*7+5=69 117
8+8*8+6=78 126
8+8*9+7=87 -121
9+7*6+0=51 99
8+7*7+5=62 110
7+7*8+6=69 117
8+7*9+6=77 125
2+6*6+0=38 86
9+6*7+3=54 102
7+6*8+5=60 108
7+6*9+6=67 115
因此您可以像这样更改代码:
int res = ((tmp[z] - '0') + (num[i] - '0') * (rhs.num[j] - '0') + (carry - '0'));
carry = (res / 10) + '0';
tmp[z] = (res % 10) + '0';
if (j == 0)
{
tmp[z - 1] = carry;
}