Java中有理数乘法的JUnit测试及方法正确性咨询
问题分析与解决方案
首先得明确:你当前的代码和测试其实完全没达到“有理数相乘”的目标,测试通过只是踩了Java整数除法的坑,而非逻辑正确。咱们一步步拆解问题,给出修正方案:
一、当前代码的核心问题
1. 方法本身偏离需求
你本意是处理Rational类型的有理数相乘,但当前方法:
public static int multiply(int a, int b) { int product = a * b; return product; }
参数和返回值都是int,完全和Rational类型无关,只是普通整数相乘,完全不符合需求。
2. 测试用例的误导性
你的测试代码:
@Test public void multiplyTest() { int product = Rational.multiply(5/7,2/3); assertEquals(product, Rational.multiply(5/7, 2/3)); // ... }
在Java中,5/7和2/3是整数除法,结果都是0——你其实在测试multiply(0,0)返回0,这当然会通过,但完全没触及有理数相乘的逻辑。
二、正确实现方案
首先需要一个Rational类来封装有理数的分子、分母,并处理约分逻辑(避免出现2/4这类未化简的情况),再实现对应的乘法方法:
1. 基础Rational类实现
public class Rational { private final int numerator; private final int denominator; // 构造方法:处理分母为0的异常,同时自动约分 public Rational(int numerator, int denominator) { if (denominator == 0) { throw new IllegalArgumentException("分母不能为0"); } // 计算最大公约数用于约分 int gcd = gcd(Math.abs(numerator), Math.abs(denominator)); // 统一符号,让分母始终为正 int sign = denominator > 0 ? 1 : -1; this.numerator = sign * numerator / gcd; this.denominator = sign * Math.abs(denominator) / gcd; } // 计算最大公约数的辅助方法 private int gcd(int a, int b) { while (b != 0) { int temp = b; b = a % b; a = temp; } return a; } // 实现有理数相乘的静态方法 public static Rational multiply(Rational r1, Rational r2) { int newNumerator = r1.numerator * r2.numerator; int newDenominator = r1.denominator * r2.denominator; return new Rational(newNumerator, newDenominator); } // 重写equals用于测试断言 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Rational rational = (Rational) o; return numerator == rational.numerator && denominator == rational.denominator; } // 可选:重写toString方便调试 @Override public String toString() { return numerator + "/" + denominator; } // 提供getter方便测试获取分子分母 public int getNumerator() { return numerator; } public int getDenominator() { return denominator; } }
2. 正确的JUnit测试用例
现在可以真正测试有理数相乘的逻辑,比如5/7 * 2/3 = 10/21:
import org.junit.Test; import static org.junit.Assert.*; public class RationalTest { @Test public void multiplyTest() { Rational r1 = new Rational(5, 7); Rational r2 = new Rational(2, 3); Rational product = Rational.multiply(r1, r2); // 方式1:断言分子分母是否正确 assertEquals(10, product.getNumerator()); assertEquals(21, product.getDenominator()); // 方式2:直接用equals断言结果对象 assertEquals(new Rational(10, 21), product); } // 额外测试带负数、需要约分的场景 @Test public void multiplyWithNegativeAndReduceTest() { Rational r1 = new Rational(-4, 6); // 化简后是-2/3 Rational r2 = new Rational(3, 8); Rational product = Rational.multiply(r1, r2); assertEquals(new Rational(-1, 4), product); } }
三、总结
- 你之前的测试通过只是整数除法的巧合,完全没有验证有理数相乘的逻辑。
- 必须先定义
Rational类封装有理数的属性和行为,再实现对应的乘法方法。 - 测试时要使用
Rational实例,而非直接写整数除法表达式,这样才能真正覆盖需求场景。
内容的提问来源于stack exchange,提问作者John Terry
相关产品推荐
相关产品推荐

