预期的测试用例失败等于输出

时间:2014-03-14 18:03:16

标签: java junit3

在我详细介绍之前,是的,这是一个家庭作业。不,我不想回答,只是提示和/或建议尝试这个或那个。

问题引入了这个:

  

创建一个类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来编写代码。

2 个答案:

答案 0 :(得分:2)

从未使用过equal方法。 assertEquals()使用的Java方法称为equalS(您必须overrideequals()派生的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。他们肯定不会是一样的。你需要

  1. 更改Add方法以返回ExactNumber对象
  2. 在ExactNumber类中有一个名为getDouble()的方法,并将其用作第二个参数。
  3. 希望这有帮助。