簡體   English   中英

Java,BigDecimal:如何對舍入錯誤進行單元測試?

[英]Java, BigDecimal: How do I unit-test for rounding errors?

我將簡要介紹一下我的實際情況:

假設我必須用Java實現一些代碼來計算加權算術平均值 我給出了兩個浮點值數組(表示為雙精度數),每個數組長度相同,第一個包含值,第二個包含各自的權重。

我們還說我做了一些實現,它返回一個表示輸入值的加權算術平均值的浮點值(也是一個double):

public static double calculateWeightedArithmeticMean(double[] values, 
        double[] weights) {

    if(values.length != weights.length) {
        throw new IllegalArgumentException();
    }

    if(values.length == 0) {
        return 0;
    }

    if(values.length == 1) {
        return new BigDecimal(values[0]).setScale(1, RoundingMode.HALF_UP).
                doubleValue();
    }

    BigDecimal dividend = BigDecimal.ZERO;
    BigDecimal divisor = BigDecimal.ZERO;
    for(int i = 0; i < values.length; i++) {
        dividend = dividend.add(new BigDecimal(values[i]).
                multiply(new BigDecimal(weights[i])));
        divisor = divisor.add(new BigDecimal(weights[i]));
    }
    if(dividend.compareTo(BigDecimal.ZERO) == 0) {
        return 0d;
    }
    return dividend.divide(divisor, 1, RoundingMode.HALF_UP).doubleValue();
}

我寫了一個單元測試,傳遞了一些值(比如,3個值+3個權重)。 我首先手動計算他們的加權算術平均值(使用計算器),然后編寫一個單元測試,檢查我的代碼是否返回該值。

我認為,由於舍入誤差,這種測試對於所使用的值的數量要大得多的情況是不相關的。 也許我實現的代碼適用於3個值+ 3個權重(對於給定的精度),因為舍入誤差小於這種情況下的精度,但是舍入誤差很可能大於1000的所需精度。值+ 1000個權重。

我的問題是:

  • 我是否還應該編寫一個單元測試來檢查大量的值(生產使用的“最壞情況”)?
  • 如果我應該,我該怎么寫呢? 如何獲得正確的值,以便我可以在我的測試斷言中使用它(手動計算2x1000值的均值似乎是一個壞主意,即使使用加權平均值計算器 ......)?
  • 類似的場景也是如此:計算幾何平均值等...

在編寫單元測試時,你總是不得不放棄某個地方。 訣竅是當你有足夠的信心時放棄:-)

在您的情況下,一些簡單的測試用例是:

  • 空數組
  • 創建第二個算法,該算法使用精確的算術(如BigDecimal輸入數組)來計算所選輸入的誤差范圍
  • 兩個數組填充相同的值。 這樣,你知道結果(它應該與單獨的第一對相同)。
    • 嘗試找到導致大舍入誤差的一對數字(如1 / 10,0.1 / 1,0.2 / 2,最終都為0.1,無法使用double正確表示; 請參見此處
  • 創建包含隨機差異的輸入數組(即+ - 1%* rand())。 隨着輸入數組的增長,這些應該均勻。

比較結果時,使用assertEquals(double, double, double) ,其中前兩個是要比較的值,最后一個是精度(逗號后3個數字為1e-3 )。

最后,您需要使用該算法並查看其行為方式。 當您發現問題時,請為此特定情況添加測試用例。

是的你應該。 測試(應該)總是涉及邊界值。

您可以提供一個epsilon邊界,您斷言答案是(大致)正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM