> Gesendet: Montag, 13. Januar 2025 um 11:45 > Von: "Frederik Ramm" <[email protected]> > An: "Christian Müller via Talk-de" <[email protected]> > Betreff: Re: [Talk-de] Genauigkeit der Koordinaten in der OSM-DB > (Nachkommastellen) > > In OSM werden die Daten intern nicht als float-Werte gespeichert, > sondern als Ganzzahlen, und vorher mit 1E7 multipliziert: > > https://github.com/openstreetmap/openstreetmap-website/blob/5d76ec051e2c429b6647401674e13688c1251956/app/models/concerns/geo_record.rb#L17-L20
Bevor die Wandlung in eine Ganzzahl erfolgt, führt die API mit den Upload-Daten das hier durch: https://github.com/openstreetmap/openstreetmap-website/blob/914fff9d4dec3d502d524f5b0f60797f66f8af65/app/models/node.rb#L91 (node.lat = OSM.parse_float...) https://github.com/openstreetmap/openstreetmap-website/blob/914fff9d4dec3d502d524f5b0f60797f66f8af65/lib/osm.rb#L510 (parse_float def) Float(..) in der Funktion parse_float wandelt eingehende Längen- und Breitengradwerte, die als Zeichenkette an die API übermittelt werd- en in den Ruby-Typ Float (laut Ruby-Dok ist das nativ float64) Neben der in der vorigen mail bereits erwähnten "Alternative mittels Zeichenkettenoperationen" zur Wandlung dieser Werte in das von der DB verwendete Ganzzahlformat, bestünde noch die Alternative mittels Decimal (in Ruby BigDecimal): -------------------------------------------------- >>> def to_int(l): ... r = Decimal(l) * Decimal('1e7') ... r = r.quantize(Decimal('1.'), rounding=ROUND_HALF_UP) ... return int(r) ... >>> to_int(1.67772165) 16777217 >>> to_int(1.67772175) 16777217 >>> Decimal(1.67772175) * Decimal('1e7') Decimal('16777217.49999999900637703831') >>> to_int('1.67772175') 16777218 Quellen: https://docs.python.org/3/library/decimal.html https://ruby-doc.org/stdlib-3.1.0/libdoc/bigdecimal/rdoc/BigDecimal.html Die letzten beiden Beispiele unterscheiden sich darin, welcher Typ dem Konstruktur von Decimal übergeben wird. Beim ersten wird das Literal 1.67772175 zunächt in den nativen Fließkommazahltyp gewandelt und dessen Wert von Decimal übernommen. Dieser Zwischenschritt enfällt, wenn Decimal direkt mit der Zeichenket- te konstruiert wird (die bei der OSM-API während des Uploads so vorliegt..). Die Ruby-Dokumentation, siehe letzte Quellen- angabe, zu BigDecimal schreibt: "Decimal arithmetic is also useful for general calculation, because it provides the correct answers people expect–whereas normal binary floating point arithmetic often introduces subtle errors because of the conversion between base 10 and base 2." Für Java existieren Angaben, dass BigDecimal um den Faktor 1000 langsamer sein kann, als Double. Außerdem wäre der Speicherbedarf etwas höher, während die API die Anfrage bearbeitet. Im Kontext Ruby lassen sich ad hoc keine brauch- baren Benchmarks finden, aber es ist anzunehmen, dass die Situation ähnlich ist. Man könnte im Ruby-Code beide (bzw. alle drei) Varianten parallel implementieren und auf einem Testserver messen, ob der Unterschied produktiv relevant wäre. Falls sich herausstellt, dass der Einsatz von Float für die Performance nicht kritisch ist, kann man die Wiedergabetreue von Werten, die an die DB übermittelt wurden, erhöhen. Ob das beim praktischen Einsatz bemerkt würde, ist eine andere Frage. Der Effekt müsste sich unabhängig davon ein- stellen, wie groß SCALE gewählt wird, also auch unter Beibehaltung des derzeitigen Werts samt 'int4'-Typ für die Datenhaltung (mini- male) Vorteile bringen. Gruß _______________________________________________ Talk-de mailing list [email protected] https://lists.openstreetmap.org/listinfo/talk-de

