2016-09-27 1 views
4

Ich verwende die Referenzimplementierung von JSR363. Ich habe viele Variationen ausprobiert, aber ich gebe diesen Code als Beispiel.Java-Einheiten der Messbibliothek Addition und Subtraktion, die falsche Werte

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)); 

Dies druckt 503,0 m. Klar ist etwas sehr falsch und das sollte 3,05 m sein. Ich finde es sehr schwer zu glauben, dass dies tatsächlich ein Fehler in der Bibliothek ist und ich hoffe, dass mir jemand sagen kann, was ich vermisse.

+0

'CENTI (SI.METRE)' wäre eine Alternative. Gibt es kein JScience-Forum? –

+0

@JoopEggen Das gleiche passiert bei der Verwendung von CENTI, ich werde versuchen, nach Foren zu suchen, aber technisch gesehen ist es nicht mehr JScience. – zjuhasz

+0

Suchen Sie nach einer neueren Version der Bibliothek, Dies muss ein nicht von der Einheit getesteter Build sein, bei dem sich jemand ernsthaft geirrt hat. –

Antwort

3

Nachdem ich ein wenig in die Sache hineingeschaut habe, konnte ich die fraglichen Kuriositäten reproduzieren. Es scheint, dass die Verwendung der Methoden multiply() oder divide() beim Übergeben einer Unit in eine QuantityFactory seltsame Auswirkungen hat. Im Beispiel:

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)) 

gibt die folgenden: 20.5 dm. Selbst wenn MetricPrefix verwendet wird, scheint dies die Standardmethode zum Setzen von Nicht-Basis-SI-Einheiten zu sein, es scheint extrem ungenau Units zu erzeugen. Verwenden Sie Folgendes:

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

Ausgänge 10020.0 km die nicht annähernd genau ist. Folgendes jedoch:

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)) 

Ausgänge 12.0 m, was natürlich die richtige Antwort ist.

In Ehrlichkeit ist die beste Lösung einfach nicht diese Operationen in der Schaffung der Quantity zu verwenden und auf andere Maßeinheiten mit der eingebauten in getConverter() von MetricPrefix Aufzählungen zu konvertieren.

Der bessere Weg Quantities zu schaffen, ist Quantities.getQuantities() zu der Einsicht von Beryllium bereitgestellt

+0

Das ist richtig, Mengen.getQuantity() teilt nicht einige der Probleme, die in NumberQuantity am gefunden werden Moment. Die RI-Version der standardmäßigen QuantityFactory gibt eine neue NumberQuantity zurück. Während der Java SE 8 Version Uom-Se nicht. Es wurde dort angesprochen, aber nicht wieder in den RI zusammengeführt. Entschuldigen Sie die Unannehmlichkeiten. Also, wenn Sie in der Lage sind, Java SE 8 oder 9 zu wählen und zu starten, versuchen Sie es mit uom-se, es sollte dort funktionieren ;-) –

2

Hinzufügen zu verwenden, kann ich das gemeldete Verhalten bestätigt und habe das Problem auf einen Fehler in der Referenzimplementierung aufgespürt. Ich habe mir die Freiheit genommen reporting the issue und meine Ergebnisse zusammen mit einer vorgeschlagenen Lösung.

In der Tat berechnet die Methode doubleValue(Unit<Q>) von NumberQuantity, die unter der Haube in Konvertierungsschritten verwendet wird, fälschlicherweise die inverse Transformation zwischen Einheiten. Dies erklärt OPs Beobachtung, dass Multiplikation und Division durch konstante Faktoren umgekehrt erscheinen, wenn sie als Einheitstransformationen angewendet werden.

Da die Standardmengenfactory ausschließlich Objekte vom Typ NumberQuantity zurückgibt, sind alle auf diese Weise erzeugten Mengen betroffen. Andere Typen wie DoubleQuantity scheinen jedoch ordnungsgemäß zu funktionieren. Wie in der Antwort von Beryllium vorgeschlagen, können sie mittels Quantities.getQuantities(<value>, <unit>) erzeugt werden. Der folgende Codeausschnitt zeigt, dass Konvertierung bricht für ein NumberQuantity aus der Standard-Fabrik erhalten, funktioniert aber richtig für ein 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))); 
    } 
} 

Dies erzeugt

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

, wo die zweite Linie ein korrektes Umwandlungsergebnis zeigt.

1

Vielen Dank für die detaillierte Beschreibung, wie das Problem reproduziert werden kann.

Die Klasse NumberQuantity verursachte ein ähnliches Problem bei einem anderen Entwickler (der sein Problem per E-Mail erläuterte). Daher sind wir uns der Verbesserung bewusst, und sobald die Fehlerbehebung abgeschlossen ist, geben wir eine Serviceversion heraus für die RI.

Regards, Werner

1

mit Release behoben 1.0.1 des JSR 363 RI.

Verwandte Themen