在我详细介绍之前,是的,这是一个家庭作业。不,我不想回答,只是提示和/或建议尝试这个或那个。
问题引入了这个:
创建一个类ExactNumber,它使用两个名为left的长属性 和右(代表左边数字部分) 和小数点右边)。例如,3.75会 用新的ExactNumber(3,7500000000000000L)表示。注意L on 告诉Java大量的结尾很长。这翻译 至:3 + 7500000000000000/10000000000000000 = 3.75
这是我的代码:
public class ExactNumber {
private long left;
private long right;
public ExactNumber(long left, long right) {
this.left = left;
this.right = right;
}
public String toString() {
return String.valueOf(doubleValue());
}
public double doubleValue() {
return ((double) left + (double) (right/ 100000000000000L) / 100);
}
public int compareTo (ExactNumber exactNumber) {
if(exactNumber.left < left) {
return 1;
}
else if (exactNumber.left == left) {
if (exactNumber.right < right) {
return 1;
}
else if (exactNumber.right == right) {
return 0;
}
else {
return -1;
}
}
else {
return -1;
}
}
public boolean equal(ExactNumber thisobject) {
if (thisobject instanceof ExactNumber) {
if (thisobject.doubleValue() == this.doubleValue()) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
public double add(ExactNumber exactNumber) {;
return ((left+exactNumber.left) + (double)((right+exactNumber.right)*1E-16));
}
}
我的问题是当预期值等于实际值时,测试会出现错误。以下是测试用例(注意:有更多测试用例,但它们通过了JUnit测试):
public class TestExactNumber extends TestCase {
ExactNumber threesevenfive = new ExactNumber(3, 7500000000000000L);
ExactNumber threesevenfive_andalittlebit = new ExactNumber(3, 7500000000000001L);
ExactNumber threesevenfive_dupe = new ExactNumber(3, 7500000000000000L);
ExactNumber ten = new ExactNumber(10, 0);
ExactNumber thirteensevenfive = new ExactNumber(13, 7500000000000000L);
ExactNumber sevenfifty = new ExactNumber(7, 5000000000000000L);
public void test_equals() {
assertFalse(threesevenfive.equals(threesevenfive_andalittlebit));
assertEquals(threesevenfive, threesevenfive_dupe);
}
public void test_add() {
assertEquals(threesevenfive.add(ten), thirteensevenfive);
assertEquals(threesevenfive.add(threesevenfive), sevenfifty);
上面的assertEquals在JUnit测试中失败了,但是说(例如)expect = 13.75和actual = 13.75。
我非常感谢您对我的代码所做的任何提示或提示。谢谢你的进步。
注意:
根据我的导师,我不应该使用doubleValue方法来实现我的equals方法。我知道我的代码中有它,但是在教师给我的提示之前,我只是不确定如何更改它。
我正在使用eclipse for java来编写代码。
答案 0 :(得分:2)
从未使用过equal
方法。 assertEquals()
使用的Java方法称为equalS
(您必须override
从equals()
派生的Object
方法。
因此,断言将使用从Object继承的equals
,它将比较实际instances
而不是使用您的equal
方法来比较objet值。而且由于它们是两种不同的实际情况,它们并不相同。
最后,这两个实例将与toString()
一起绘制,结果为expected = 13.75 and actual = 13.75.
(因为你的toString()仅返回值,忽略实例之间的差异)
您的教师回应: Java中的Long是一个64位长的数字。 Java中的Double是使用IEEE754标准实现的,尾数只留下52位。含义:任何将长数字转换为双精度数,其中长数字在第53位到第63位上具有设置位 - 将导致指数以某种方式移位,使得您在LSB周围的精度降低 - 导致双重价值的前提。
因此,比较双值以确定相等性并不足以满足您所需的&#34;确切数字&#34;。
的设计。示例:
Long bigLong = 1L<<51; //picked 51: 52 and 53 already causing rounding issues.
Long long1 = bigLong + 1L;
Long long2 = bigLong + 2L;
System.out.println(long1+" -> " + long1.doubleValue());
System.out.println(long2+" -> " + long2.doubleValue());
//false, enough precision to preserve bit "0" and "1".
System.out.println(long1.doubleValue()==long2.doubleValue());
输出:
2251799813685262 -> 2.251799813685262E15
2251799813685263 -> 2.251799813685263E15
false
设置位54时:
Long bigLong = 1L<<54;
Long long1 = bigLong + 1L;
Long long2 = bigLong + 2L;
System.out.println(long1+" -> " + long1.doubleValue());
System.out.println(long2+" -> " + long2.doubleValue());
System.out.println(long1.doubleValue()==long2.doubleValue());
输出:
18014398509481985 -> 1.8014398509481984E16
18014398509481986 -> 1.8014398509481984E16
true
注意Exponent being从15增加到16,这将切断&#34; 1&#34;两个长期之间。
要解决此问题,您可以将 left1 与 left2 和 right1 与 right2 进行比较,而无需将其转换为双
答案 1 :(得分:0)
你的平等方法应该理想地测试你班级中的每一个必要值。在这种情况下,应该检查两个对象之间的左右值是否相同。如果它们相同,那么您可以认为对象是相同的。
在您的情况下,您应该在equals方法中放置一个调试点,以查看函数返回false的原因。
尝试使用Eclipse的内置功能为您创建equals和hashcode方法。你可以通过转到Source-&gt;生成hashCode()和equals()来创建它。这些方法与您创建的方法有很大不同。
另一方面,在AssertEquals方法中,确保传入的值都是相同的类型。在您的情况下,您使用ExactNumber对象检查Double。他们肯定不会是一样的。你需要
希望这有帮助。