本题要求解一个合法的一元一次方程,方程中只包含整数、一个小写字母(未知数)以及 +、-、= 三个符号。我们需要将方程化简为 ax = b 的形式,然后求解 x = b/a。
核心思想是一边读入一边处理,将方程化简为系数和常数的形式:
kb最终方程变为:k * 未知数 = b,解为 x = b / k
| 变量 | 含义 |
|---|---|
k | 未知数的系数总和 |
b | 常数项总和(移到右边后的值) |
f | 当前项的符号,1 为正,-1 为负 |
now | 当前在等号哪一侧,1 为左,-1 为右 |
x | 当前读取到的数字 |
r | 是否读取到了数字(用于判断系数是否为1) |
遍历每个字符时,根据字符类型分别处理:
+ 或 -遇到运算符时,说明前一个数字/项已经结束,将之前累积的常数项加入到 b 中,然后重置 x = 0,更新符号 f。
=遇到等号时,同样先将之前的常数项加入 b,然后重置状态,并将 now 设为 -1(表示移到右边)。
r == true),说明系数是 x,将 now * f * x 累加到 kr == false),说明系数是 1,将 now * f 累加到 ka累积数字到 x 中,并标记 r = true。
循环结束后,最后一项可能还未被加入,需要额外处理:
cpp1b += now * f * x; // 加上最后一项常数
ans = -b / k // 因为 b 是移项到右边的值,实际方程是 k*x + b = 0
注意特殊处理 -0.0 的情况,将其修正为 0.0。
cpp1#include <iostream> 2#include <cstdio> 3using namespace std; 4 5char c, a; // c用来读入,a是未知数名 6int f = 1, now = 1, k = 0, b = 0, x = 0; // f符号,now左右侧,k系数,b常数,x当前数字 7bool r = false; // 是否读入过数字 8 9int main() { 10 while (cin >> c) { 11 if (c == '-') { 12 b += now * f * x; 13 x = 0; 14 f = -1; 15 r = false; 16 } 17 if (c == '+') { 18 b += now * f * x; 19 x = 0; 20 f = 1; 21 r = false; 22 } 23 if (c == '=') { 24 b += now * f * x; 25 x = 0; 26 f = 1; 27 now = -1; 28 r = false; 29 } 30 if (c >= 'a' && c <= 'z') { 31 if (r) { 32 k += now * f * x; 33 x = 0; 34 } else { 35 k += now * f; 36 } 37 a = c; 38 r = false; 39 } 40 if (c >= '0' && c <= '9') { 41 x = x * 10 + (c - '0'); 42 r = true; 43 } 44 } 45 46 // 处理最后一项 47 b += now * f * x; 48 49 double ans = -1.0 * b / k; 50 if (ans == -0.0) ans = 0.0; // 消除 -0.0 51 52 printf("%c=%.3lf\n", a, ans); 53 return 0; 54}
输入:6a-5+1=2-2a
处理过程:
输出:a=0.750
a 或 -a)时,系数应为 1 或 -1,通过 r 标志来判断。f 记录当前符号,now 记录等号左右侧,两者相乘决定最终符号。now = -1 实现。-0.000 的特殊情况。