我想检查相等的2个分数。我认为我写的方法不正确,因为可能会失去准确性。我是对还是错?
public boolean equals(Rational r) {
return (double) numerator / denominator == (double) r.numerator / r.denominator;
}
答案 0 :(得分:5)
我认为这会更好:
public boolean equals(Rational r) {
return numerator * r.denominator == r.numerator * denominator;
}
答案 1 :(得分:2)
你是对的,这种检查在很多情况下会失败。
使其工作的唯一方法是将结果转换为BigDecimal或String,然后比较或定义允许的错误 - 即:
public boolean equals(Rational r) {
double c1 = ((double) numerator) / denominator;
double c2 = ((double) r.numerator) / r.denominator;
return c2 > (c1-allowedError) && c2 < (c1+allowedError);
}
答案 2 :(得分:1)
你可以这样做
public boolean equals(Rational r) {
return numerator * r.denominator == r.numerator * denominator;
}
答案 3 :(得分:1)
如果你的理性减少了分子和分母之外的所有常见因素,那么你可以这样做:
return (numerator == r.numerator) && (denominator == r.denominator);
如果您的理性不已完成该分解,那么我建议您实施一个允许您这样做的GCD功能。然后将缩小的numerator
和denominator
与缩减的r.numerator和r.denominator
进行比较。
示例,假设int
是理性分子和分母的基础类型:
int gcd_lhs = gcd( numerator, denominator );
int gcd_rhs = gcd( r.numerator, r.denominator );
int lhs_red_num = numerator / gcd_lhs;
int lhs_red_den = denominator / gcd_lhs;
int rhs_red_num = r.numerator / gcd_rhs;
int rhs_red_den = r.denominator / gcd_rhs;
return (lhs_red_num == rhs_red_num) && (lhs_red_den == rhs_red_den);
这种方法的优点是在所有情况下都是精确的,并且它永远不会超过你用于分子和分母的基础类型的精度。
依赖乘法或除了GCD风险以外的值除以基础类型中可用精度的方法。 (除非首先转换为double
,否则可以通过生成一个必须舍入以适应可用位的重复二进制小数来“溢出”可用精度。除以GCD总是精确的,并保持为整数除法。 )
您可以通过使用BigInteger类型并应用交叉乘法方法来缓解这种情况。这有其自身的成本。如果您已经使用BigInteger来存储分子和分母,那么这可能是最简单的方法。
答案 4 :(得分:0)
执行此操作的一种方法如下:
boolean eq = Math.abs( (double) numerator / denominator -
(double) r.numerator / r.denominator ) < EPS;
其中
EPS是一些小的正常数,例如EPS=0.00001
。
如果eq
变量设置为true,则表示您的数字“相等”
除了您想忽略的可能的精度错误。
当然在Java操作中有浮点
与许多其他语言一样,数字不是100%精确
或者,正如其他人在此建议的那样,
你可以决定不使用双打
特别的任务/但你不能总是避免它们;)/
答案 5 :(得分:0)
在双元浮点系统中使用==和双精度可能是危险的,因为某些分数(包括十进制中可表达的一些分数)can't be expressed
你可以重新排列方程,这样你就不需要双打(假设你的分子和分母是整数)
r.denominator*numerator==denominator*r.numerator