【C++】双温度转换与并联电阻计算的编程题分析与优化
文章目录
- 💯前言
- 💯从华氏温度到摄氏温度的转换
- 题目背景与华氏温度与摄氏温度的转换
- 初始代码与验证通过的解法
- 代码分析
- 特点与优缺点
- 老师的代码:结合 C 与 C++ 的风格
- 代码分析与对比
- 改进建议
- 现代 C++ 的改进代码
- 💯并联电阻的计算
- 初始代码与验证通过的解法
- 代码分析
- 改进建议
- 老师的代码:结合 C 与 C++ 的风格
- 代码分析
- 改进建议
- 💯小结
💯前言
- 在编写数值计算程序时,准确性 和 代码的可维护性 是两个核心的目标。本篇文章通过两道与 物理计算 相关的编程题目深入探讨了
温度转换
和电阻并联计算
的代码实现方式。通过比较不同的代码风格以及现代化编程的改进,旨在帮助读者理解如何编写更加 高效、简洁、且符合 现代编程规范 的代码。在此过程中,文章不仅涵盖了基础的算法实现,还特别强调了 输入输出的最佳实践、浮点数的精确控制
、以及 代码模块化 的设计方法,以适应日益复杂的编程需求。
C++ 参考手册
💯从华氏温度到摄氏温度的转换
温度表达转化
题目要求我们利用公式将华氏温度转换为摄氏温度,具体要求如下:
- 使用公式:
C = 5 × ( F − 32 ) 9 C = \frac{5 \times (F - 32)}{9} C=95×(F−32)
其中 F F F表示输入的华氏温度, C C C表示输出的摄氏温度。
-
输入格式:
- 输入一行,包含一个实数
F
F
F,表示华氏温度。
- F ≥ − 459.67 F \ge -459.67 F≥−459.67(即温度不能低于绝对零度)。
- 输入一行,包含一个实数
F
F
F,表示华氏温度。
-
输出格式:
- 输出一行,包含一个实数 C C C,表示对应的摄氏温度,要求输出精确到小数点后 5 位。
-
输入输出示例:
- 输入:
41
- 输出:
5.00000
- 输入:
题目背景与华氏温度与摄氏温度的转换
华氏温度和摄氏温度是两种常用的温度计量单位。在科学计算中,理解温度的转换非常重要。公式如下:
C = 5 × ( F − 32 ) 9 C = \frac{5 \times (F - 32)}{9} C=95×(F−32)
该公式中,摄氏温度 C C C是通过从华氏温度 F F F中减去 32,然后乘以 5/9 来计算的。这是因为华氏和摄氏的比例关系以及他们的起始基准点的不同。对于编程的任务来说,除了正确的计算外,格式化输出的要求也非常重要,这就是本题中要求精确到小数点后 5 位的部分。
初始代码与验证通过的解法
首先,是我编写的第一份代码,该代码是用C语言风格解决的,具体如下:
#include <cstdio>
int main() {
double F; // 定义变量 F 存储华氏温度
scanf("%lf", &F); // 从用户输入读取 F 的值
printf("%.5f", 5.0 * (F - 32) / 9); // 按格式保留 5 位小数输出计算结果
return 0;
}
代码分析
-
输入部分:
- 使用
scanf
从标准输入读取一个浮点数,并赋值给F
。%lf
用于读取类型为double
的数据。
- 使用
-
计算部分:
- 使用公式 5.0 × ( F − 32 ) / 9 5.0 \times (F - 32) / 9 5.0×(F−32)/9进行计算。
- 使用
5.0
而非5
是为了确保浮点数计算,避免整数除法带来的精度丢失问题。
-
输出部分:
- 使用
printf("%.5f", c)
,其中%.5f
保证输出结果精确到小数点后 5 位。
- 使用
特点与优缺点
-
优点:
- 代码简洁,直接利用
scanf
和printf
进行输入输出,符合C语言风格。 - 使用浮点数
5.0
来保证计算的精度。
- 代码简洁,直接利用
-
缺点:
- 使用了C语言风格的输入输出,虽然简洁,但与C++的标准流风格(
cin
/cout
)不一致,不符合现代C++的推荐实践。
- 使用了C语言风格的输入输出,虽然简洁,但与C++的标准流风格(
老师的代码:结合 C 与 C++ 的风格
老师在课堂上的代码使用了一种折衷的方式,将 C++ 的输入方式与 C 的输出方式结合在了一起。代码如下:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double F;
cin >> F; // 使用 cin 从标准输入读取 F
double c = 5 * (F - 32) / 9; // 按公式计算摄氏温度
printf("%.5f", c); // 使用 printf 输出结果,保留 5 位小数
return 0;
}
代码分析与对比
-
输入部分:
- 老师的代码使用了
cin
来读取输入。这是 C++ 标准流的一部分,使得代码更现代化,易于理解。
- 老师的代码使用了
-
输出部分:
- 老师保留了
printf
进行输出,这种风格在一些场合下更容易实现精确的格式化输出,但它与cin
风格不完全统一。
- 老师保留了
改进建议
为了让代码更加符合现代 C++ 风格,建议将输出部分也改为 cout
,并结合 iomanip
进行格式化输出。
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double F;
cin >> F; // 从用户输入获取华氏温度
double c = 5.0 * (F - 32) / 9; // 计算摄氏温度
cout << fixed << setprecision(5) << c << endl; // 格式化输出
return 0;
}
现代 C++ 的改进代码
在这份代码中,我们完全使用了 C++ 的输入输出方式,使得代码更易读,并且更符合现代 C++ 的推荐风格。
-
cin
和cout
:- 使用
cin
进行输入,cout
进行输出,这样可以使代码具有更高的可读性,且更符合 C++ 面向对象的设计理念。
- 使用
-
格式化输出:
fixed
和setprecision(5)
用于控制cout
的输出格式,fixed
表示定点格式输出,setprecision(5)
用于控制保留到小数点后 5 位。
💯并联电阻的计算
计算并联电阻的阻值
对于阻值为 r 1 r_1 r1和 r 2 r_2 r2的电阻,其并联电阻值公式计算如下:
R = 1 1 r 1 + 1 r 2 R = \frac{1}{\frac{1}{r_1} + \frac{1}{r_2}} R=r11+r211
-
输入格式:
- 输入两个实数 r 1 , r 2 r_1, r_2 r1,r2,以一个空格分开。
-
输出格式:
- 输出并联之后的阻抗大小,结果保留小数点后 2 位。
-
输入输出示例:
- 输入:
1 2
- 输出:
0.67
- 输入:
初始代码与验证通过的解法
首先,我们来看您编写的代码,该代码通过了测试,具体如下:
#include <cstdio>
int main() {
int r1, r2;
double R;
scanf("%d %d", &r1, &r2);
R = 1.0 / ((1.0 / r1) + (1.0 / r2));
printf("%.2lf", R);
return 0;
}
代码分析
-
变量类型:
r1
和r2
使用int
类型来读取。这种情况下,如果电阻值是浮点数,会失去精度。因此,改进时可以将r1
和r2
定义为double
,这样可以处理浮点数输入。
-
并联计算:
R = 1.0 / ((1.0 / r1) + (1.0 / r2));
这里正确地将1.0
作为除数,确保运算结果是浮点数。这样避免了整数除法带来的精度丢失。
-
输入输出:
- 使用
scanf
读取输入,printf
格式化输出,%.2lf
表示保留 2 位小数输出结果。
- 使用
改进建议
-
变量类型统一为浮点数:
- 将
r1
和r2
都声明为double
类型,以确保能处理更精确的输入。 - 代码改进如下:
#include <cstdio> int main() { double r1, r2, R; scanf("%lf %lf", &r1, &r2); R = 1.0 / ((1.0 / r1) + (1.0 / r2)); printf("%.2lf\n", R); return 0; }
- 将
-
使用现代 C++ 风格:
-
为了符合现代 C++ 的风格,可以使用
iostream
和iomanip
进行输入和格式化输出:#include <iostream> #include <iomanip> using namespace std; int main() { double r1, r2; cin >> r1 >> r2; double R = 1.0 / ((1.0 / r1) + (1.0 / r2)); cout << fixed << setprecision(2) << R << endl; return 0; }
-
这里的
fixed
和setprecision(2)
用于控制小数点后的位数。
-
-
输入校验:
- 可以考虑对输入进行简单的检查,例如,电阻值不能为 0,否则会导致除以零的错误。
if (r1 == 0 || r2 == 0) { cout << "Invalid input: Resistance cannot be zero." << endl; return 1; // 非正常退出 }
- 可以考虑对输入进行简单的检查,例如,电阻值不能为 0,否则会导致除以零的错误。
-
代码的结构化与可维护性:
- 可以考虑将并联电阻的计算提取为一个函数,方便代码的复用和结构化。
double calculate_parallel_resistance(double r1, double r2) { if (r1 == 0 || r2 == 0) { throw invalid_argument("Resistance cannot be zero"); } return 1.0 / ((1.0 / r1) + (1.0 / r2)); }
- 然后在主函数中调用这个计算函数,这样使得代码更加清晰和模块化:
int main() { double r1, r2; cin >> r1 >> r2; try { double R = calculate_parallel_resistance(r1, r2); cout << fixed << setprecision(2) << R << endl; } catch (const invalid_argument& e) { cout << e.what() << endl; } return 0; }
- 可以考虑将并联电阻的计算提取为一个函数,方便代码的复用和结构化。
老师的代码:结合 C 与 C++ 的风格
老师在课堂上的代码如下:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double r1, r2;
cin >> r1 >> r2;
double r = 1 / (1 / r1 + 1 / r2);
printf("%.2lf\n", r);
return 0;
}
代码分析
-
输入方式:
- 使用
cin
进行输入,符合 C++ 标准流风格,使得代码更现代化。
- 使用
-
输出方式:
- 使用了
printf
,这是一种 C 风格的输出方式,与cin
不完全匹配。
- 使用了
改进建议
-
输入输出风格统一:
- 建议改为
cout
,结合iomanip
,使代码更加符合 C++ 风格:#include <iostream> #include <iomanip> using namespace std; int main() { double r1, r2; cin >> r1 >> r2; double r = 1 / (1 / r1 + 1 / r2); cout << fixed << setprecision(2) << r << endl; return 0; }
- 建议改为
-
健壮性与可读性:
- 增加输入检查,避免输入 0 值导致除零错误,使代码更加健壮。
-
模块化改进:
- 将计算提取到函数中,有助于提高代码的可读性和维护性,同时便于测试和复用。
double calculate_parallel_resistance(double r1, double r2) { return 1 / (1 / r1 + 1 / r2); } int main() { double r1, r2; cin >> r1 >> r2; if (r1 == 0 || r2 == 0) { cout << "Invalid input: Resistance cannot be zero." << endl; return 1; } double r = calculate_parallel_resistance(r1, r2); cout << fixed << setprecision(2) << r << endl; return 0; }
- 将计算提取到函数中,有助于提高代码的可读性和维护性,同时便于测试和复用。
💯小结
通过这两道题的讨论,我们学习了如何利用 C 和 C++ 的不同输入输出风格 解决问题,并且了解了如何改进代码使其更符合 现代 C++ 的编程习惯。同时,通过增加必要的输入检查
,代码的健壮性也能得到提高。此外,我们还学习了如何利用 模块化的方法,使代码更具结构化和可维护性。在编写高质量代码时,保持 风格的一致性、增加必要的 输入验证、以及 模块化设计,都是非常重要的编码实践。这些技巧不仅有助于代码的可读性和维护性,还能帮助我们更有效地处理复杂的逻辑和潜在的错误情况
。