Hallo Christian,
ich habe Dich mit meinem Link zur Ruby-Dokumentation da ein bisschen in
die falsche Richtung geschickt. Die Ruby-basierte Webseite ist zwar
unsere "Referenz-Implementation", was die API-Funktionen anbetrifft und
auch solche Fragen wie "was für ein Datenbanktyp wird für die
Eigenschaft X genutzt".
Wenn Du aber so tief einsteigen möchtest, dass Du genau analysierst, ob
und wann ein Wert zwischendurch vielleicht mal ein Float ist, dann
verlässt Du den Berech der "Referenz-Implementation" und musst in den
Code gucken, der in der Praxis auf openstreetmap.org eingesetzt wird.
Das ist aber für die allermeisten daten-bezogenen API-Funktionen (nicht
für alle) inzwischen "cgimap", welches in C++ und nicht in Ruby
geschrieben ist, siehe https://wiki.openstreetmap.org/wiki/CGImap.
Es ist natürlich durchaus möglich, dass Deine Anmerkungen dort genauso
gelten, ich habe mir das nicht genau angeschaut.
Bye
Frederik
On 15/01/2025 10:05, Christian Müller via Talk-de wrote:
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
--
Frederik Ramm ## eMail [email protected] ## N49°00'09" E008°23'33"
_______________________________________________
Talk-de mailing list
[email protected]
https://lists.openstreetmap.org/listinfo/talk-de