有理数对象赋值时的约分实现问题求助
问题分析与修复方案
你的两个构造函数都存在问题,导致无法正确约分并赋值给成员变量,逐一拆解问题并给出修复后的实现:
原代码的核心问题
第一个构造函数
- 重复计算gcd:两次调用
gcd(num, denom),虽结果一致但属于冗余计算 - 未前置检查分母合法性:
gcd函数在b=0时直接返回a,但分母为0是非法状态,应在计算前就判断并抛出异常——构造函数内catch异常会导致对象处于未初始化的无效状态 - 符号处理缺失:输入
-10/20或10/-20这类带负号的数值时,约分后符号逻辑会混乱,需统一将分母转为正数,符号转移到分子上
第二个构造函数
- 修改对象错误:最后两行
num /= ...和denom /= ...仅修改了构造函数的形参,而非this->num和this->denom成员变量,因此成员变量始终是原始赋值的未约分状态 - 同时存在第一个构造函数的分母检查、符号处理问题
修复后的构造函数实现
#include "GCD.h" #include "RationalException.h" // 假设你已定义该异常类 Rational::Rational(int num, int denom) { // 第一步:前置检查分母合法性,非法则抛出异常 if (denom == 0) { throw RationalException("Denominator cannot be zero"); } // 第二步:计算分子分母的最大公约数,取绝对值避免负数干扰gcd计算 int common_divisor = gcd(abs(num), abs(denom)); // 第三步:约分,并统一符号(保证分母为正,符号移至分子) this->num = num / common_divisor; this->denom = denom / common_divisor; if (this->denom < 0) { this->num *= -1; this->denom *= -1; } }
关键细节说明
- 前置合法性检查:在任何计算前判断分母是否为0,抛出异常让调用者处理,避免构造出无效的Rational对象
- 单次计算gcd:先算出公约数再复用,提升执行效率
- 绝对值计算gcd:
gcd函数逻辑针对非负数设计,用abs()确保输入为正,避免负数导致的计算错误 - 统一分母符号:保证分母始终为正,让后续加减乘除的逻辑更统一,例如
10/-20会被转为-1/2
gcd函数的小优化
你的gcd函数在输入负数时可能返回负数(如gcd(-10,20)会返回-10),可以修改函数本身确保返回正的公约数:
inline int gcd(int a, int b) { a = abs(a); b = abs(b); return b == 0 ? a : gcd(b, a % b); }
内容的提问来源于stack exchange,提问作者Stephen
相关产品推荐
相关产品推荐

