簡體   English   中英

Java單位的測量庫加法和減法返回不正確的值

[英]Java units of measurement library addition and subtraction returning incorrect values

我正在使用JSR363的參考實現。 我嘗試了很多這方面的變化,但我會以此代碼為例。

ServiceProvider provider = ServiceProvider.current();
QuantityFactory<Length> lengthFactory = provider.getQuantityFactory(Length.class);
Quantity<Length> first = lengthFactory.create(5, Units.METRE.divide(100.0));
Quantity<Length> second = lengthFactory.create(3, Units.METRE);
System.out.println(second.add(first));

這打印503.0米。 顯然有些東西是非常錯誤的,這應該是3.05米。 我發現很難相信這實際上是圖書館的一個錯誤,我希望有人可以告訴我我錯過了什么。

在研究了一下后,我已經能夠重現有問題的怪異。 看起來在將Unit傳遞給QuantityFactory時使用multiply()divide()方法會產生奇怪的效果。 例如:

Quantity firstQuant = quantFactory.create(10.0,Units.METRE)
Quantity secondQuant = quantFactory.create(20.0,Units.METRE.divide(10.0))
System.out.println(secondQuant.add(firstQuant))

輸出以下內容: 20.5 dm 即使使用MetricPrefix ,它似乎是設置非基本SI單位的默認方法,它似乎生成非常​​不准確的Units 使用以下內容:

Quantity secondQuant = quantFactory.create(20.0,MetricPrefix.KILO(Units.METRE))

輸出10020.0 km ,這遠不准確。 但是,以下內容:

Quantity firstQuant = quantFactory.create(10.0,Units.METRE)
Quantity secondQuant = quantFactory.create(20.0,Units.METRE)
System.out.println(secondQuant.divide(10.0).add(firstQuant))

輸出12.0 m ,這顯然是正確的答案。

誠實地說,最好的解決方案是在創建Quantity不使用這些操作,並使用MetricPrefix枚舉的內置getConverter()轉換為其他測量單位。

創建Quantities的更好方法是使用Quantities.getQuantities()

添加到Beryllium提供的洞察力,我可以確認報告的行為,並已將問題跟蹤到參考實現中的錯誤。 我冒昧地報告了這個問題和我的發現以及一個提議的解決方案。

實際上, NumberQuantity的方法doubleValue(Unit<Q>)在轉換步驟的引擎蓋下使用,會錯誤地計算單位之間的逆變換。 這解釋了OP的觀察結果,當作為單位變換應用時,常數因子的乘法和除法似乎是相反的。

由於默認數量工廠專門返回NumberQuantity類型的對象, NumberQuantity這種方式創建的所有數量都會受到影響。 但是,像DoubleQuantity這樣的其他類型似乎可以正常工作。 正如Beryllium在答案中所建議的那樣,它們可以通過Quantities.getQuantities(<value>, <unit>) 以下代碼段演示了從默認工廠獲取的NumberQuantity轉換中斷,但對DoubleQuantity正常工作:

package test.jsciunits;

import javax.measure.spi.ServiceProvider;
import javax.measure.Quantity;
import javax.measure.quantity.Length;
import javax.measure.spi.QuantityFactory;
import tec.units.ri.quantity.Quantities;
import static tec.units.ri.unit.Units.*;
import static tec.units.ri.unit.MetricPrefix.*;

public class JScienceUnits {
    public static void main(String[] args) {
        ServiceProvider provider = ServiceProvider.current();
        QuantityFactory<Length> lengthFactory = provider.getQuantityFactory(Length.class);

        Quantity<Length> q = lengthFactory.create(5.0, METRE);
        Quantity<Length> r = Quantities.getQuantity(5.0,  METRE);

        System.out.println("q = " + q + ", q.to(CENTI(METRE)) = " + q.to(CENTI(METRE)));
        System.out.println("r = " + r + ", r.to(CENTI(METRE)) = " + r.to(CENTI(METRE)));
    }
}

這產生了

q = 5.0 m, q.to(CENTI(METRE)) = 0.05 cm
r = 5.0 m, r.to(CENTI(METRE)) = 500.0 cm

第二行顯示正確的轉換結果。

感謝有關如何重現該問題的詳細說明。

據報道, NumberQuantity類引起了另一個開發人員的類似問題(他通過電子郵件解釋了他的問題)所以我們知道要改進的事情,當修復完成后,我們將為RI發布服務版本。

此致,Werner

修復了JSR 363 RI的1.0.1版。

暫無
暫無

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

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