Java单位的测量库加法和减法返回不正确的值

时间:2016-09-27 06:41:26

标签: java jscience jsr363

我正在使用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米。我发现很难相信这实际上是图书馆的一个错误,我希望有人可以告诉我我错过了什么。

4 个答案:

答案 0 :(得分:4)

在研究了一下后,我已经能够重现有问题的怪异。将multiply()传递给QuantityFactory时,使用divide()Unit方法似乎有奇怪的效果。例如:

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时不使用这些操作,并使用内置的getConverter() MetricPrefix枚举转换为其他测量单位。

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

答案 1 :(得分:2)

根据Beryllium提供的见解,我可以确认报告的行为,并将问题跟踪到参考实现中的错误。我冒昧地reporting the issue和我的发现以及提议的解决方案。

实际上,在转换步骤中使用的doubleValue(Unit<Q>)方法NumberQuantity错误地计算了单位之间的逆变换。这解释了OP的观察结果,当作为单位变换应用时,常数因子的乘法和除法似乎是相反的。

由于默认数量工厂专门返回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

其中第二行显示正确的转换结果。

答案 2 :(得分:1)

感谢有关如何重现该问题的详细说明。

据报道 NumberQuantity 类引起了另一位开发人员的类似问题(他通过电子邮件解释了他的问题)所以我们知道要改进的事情以及修复完成后我们会发布RI的服务版本。

此致 沃纳

答案 3 :(得分:1)

修复了JSR 363 RI的发布1.0.1