本文将介绍如何通过C++字符串操作实现支持整数、分数、小数的高精度四则运算。代码通过字符串解析和分数运算,避免了浮点数精度丢失问题。
输入
3.0 3/4
输出
( 3.0 ) + ( 3/4 ) = ( 15/4 )
( 3.0 ) - ( 3/4 ) = ( 9/4 )
( 3.0 ) * ( 3/4 ) = ( 9/4 )
( 3.0 ) / ( 3/4 ) = ( 4 )
输入(3/-999自动兼容为-3/999)
50 3/-999
输出
( 50 ) + ( 3/-999 ) = ( 16649/333 )
( 50 ) - ( 3/-999 ) = ( 16651/333 )
( 50 ) * ( 3/-999 ) = ( -50/333 )
( 50 ) / ( 3/-999 ) = ( -16650 )
输入
-256 -66.6
输出
( -256 ) + ( -66.6 ) = ( -1613/5 )
( -256 ) - ( -66.6 ) = ( -947/5 )
( -256 ) * ( -66.6 ) = ( 85248/5 )
( -256 ) / ( -66.6 ) = ( 1280/333 )
#include
using namespace std;
typedef long long ll;
// 求最大公约数
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}
// 求最小公倍数
ll lcm(ll a, ll b)
{
return a * b / gcd(a, b);
}
// 字符串识别规则,输出{分子, 分母}(只能识别整数、分数、小数,需保证数据正常)
pair<ll, ll> identity(string st)
{
int p1 = -1, p2 = -1;
for (int i = 0; i < st.length(); i++)
{
if (st[i] == '/')
p1 = i;
if (st[i] == '.')
p2 = i;
}
// 三种情况(整数、分数、小数)
pair<ll, ll> result;
// 整数
if (p1 == -1 && p2 == -1)
{
result = {stoll(st), 1LL};
}
// 分数
else if (p1 != -1 && p2 == -1)
{
result = {stoll(st.substr(0, p1)), stoll(st.substr(p1 + 1, st.length() - 1 - p1))};
}
// 小数
else if (p1 == -1 && p2 != -1)
{
string st2 = "1";
for (int i = 0; i < st.length() - 1 - p2; i++)
st2 += '0';
result = {stoll(st.substr(0, p2) + st.substr(p2 + 1, st.length() - 1 - p2)), stoll(st2)};
}
// 判断分母是否为零
if (result.second == 0)
{
fprintf(stderr, "[ERROR] Division by zero detected at %s:%d\n", __FILE__, __LINE__);
std::exit(EXIT_FAILURE);
}
// 约分操作
ll gcd_result = gcd(result.first, result.second);
result.first /= gcd_result, result.second /= gcd_result;
// 格式化操作(防止出现-3/-4或3/-4)
if (result.first < 0 && result.second < 0 || result.first > 0 && result.second < 0)
result.first = 0 - result.first, result.second = 0 - result.second;
return result;
}
// string表达格式化(-3/-4 => 3/4 、 6/-12 => -1/2)
string init(string st)
{
pair<ll, ll> x = identity(st);
if (x.second == 1)
return to_string(x.first);
return to_string(x.first) + '/' + to_string(x.second);
}
// 加法
string add(string a, string b)
{
pair<ll, ll> x = identity(a), y = identity(b);
// n1、n3分别为a、b分子,n2、n4分别为a、b分母
ll n1 = x.first, n2 = x.second, n3 = y.first, n4 = y.second;
// a + b = (n1*n4 + n2*n3) / (n2*n4)
string result = init(to_string(n1 * n4 + n2 * n3) + '/' + to_string(n2 * n4));
return result;
}
// 减法
string sub(string a, string b)
{
pair<ll, ll> x = identity(a), y = identity(b);
// n1、n3分别为a、b分子,n2、n4分别为a、b分母
ll n1 = x.first, n2 = x.second, n3 = y.first, n4 = y.second;
// a - b = (n1*n4 - n2*n3) / (n2*n4)
string result = init(to_string(n1 * n4 - n2 * n3) + '/' + to_string(n2 * n4));
return result;
}
// 乘法
string mul(string a, string b)
{
pair<ll, ll> x = identity(a), y = identity(b);
// n1、n3分别为a、b分子,n2、n4分别为a、b分母
ll n1 = x.first, n2 = x.second, n3 = y.first, n4 = y.second;
// a * b = (n1*n3) / (n2*n4)
string result = init(to_string(n1 * n3) + '/' + to_string(n2 * n4));
return result;
}
// 除法
string div(string a, string b)
{
pair<ll, ll> x = identity(a), y = identity(b);
// n1、n3分别为a、b分子,n2、n4分别为a、b分母
ll n1 = x.first, n2 = x.second, n3 = y.first, n4 = y.second;
// a / b = (n1*n4) / (n2*n3)
string result = init(to_string(n1 * n4) + '/' + to_string(n2 * n3));
return result;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
string a, b;
cin >> a >> b;
cout << "( " + a + " )" + " + " + "( " + b + " )" + " = " + "( " + add(a, b) + " )" << endl;
cout << "( " + a + " )" + " - " + "( " + b + " )" + " = " + "( " + sub(a, b) + " )" << endl;
cout << "( " + a + " )" + " * " + "( " + b + " )" + " = " + "( " + mul(a, b) + " )" << endl;
cout << "( " + a + " )" + " / " + "( " + b + " )" + " = " + "( " + div(a, b) + " )" << endl;
return 0;
}