> 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
> 
> Bye
> Frederik


In derselben ruby Datei finden sich ab Zeile 40
Umrechnungsfunktionen für Fließkommaeingabewerte,
welche die Funktion "round" nach der Skalierung
verwenden.

Das kann merkwürdige Effekte haben:

>>> round(0.00000095*1e7)
10
>>> round(0.00000085*1e7)
8
>>> round(179.99999995*1e7)
1800000000
>>> round(179.99999985*1e7)
1799999998

>>> float(int(round(179.99999995*1e7)))/1e7
180.0
>>> float(int(round(179.99999985*1e7)))/1e7
179.9999998

>>> float(int(round((-3+.99999995)*1e7)))/1e7
-2.0
>>> float(int(round((-2+.99999995)*1e7)))/1e7
-1.0000001

Die letzten Zeilen simulieren (hier mit python)
Wandlung zu int4 und Rückwandlung zu float für den
Datenabruf.

Für einen Nutzer wird dieses Phänomen so deutlich,
dass manche Koordinaten nach Osten, manche leicht
nach Westen verschoben werden, wenn ein hochge-
ladener und anschließend wieder abgerufener Daten-
satz Längenangaben ursprünglich so enthielt, dass
sie nahe oder auf der Mitte zweier benachbarter,
von der DB repräsentierbaren Werte lagen.

(bei Editoren, welche keine höhere Präzision als
die der DB bei der Erfassung und Darstellung ver-
wenden oder zulassen ist das irrelevant)


Mit der angesprochenen Präzision von 10 cm am
Äquator, läge der Fehler der dadurch entsteht im
ungünstigsten Fall bei 5 cm, rundungsbezogen wie
angesprochen mal nach Osten, mal nach Westen ver-
setzt.



Dieses Problem bestünde bei der Einführung einer
oder mehrerer weiterer Nachkommastellen fort,
dann kleinere Distanzen betreffend.  Die Ursache
liegt darin begründet, dass nicht alle reellen
Werte mit IEEE-Fließkommazahlen darstellbar sind.
Da die Lücken nicht gleichverteilt sind, spielt
es z.B. auch eine Rolle, ob vor oder nach der
Skalierung gerundet wird:

>>> float(int(round(3+.99999995, 7)*1e7))/1e7
3.9999999
>>> float(int(round((3+.99999995)*1e7)))/1e7
4.0


Anschauungsbeispiel(e):
https://commons.wikimedia.org/wiki/File:FloatingPointPrecisionAugmented.png
https://commons.wikimedia.org/wiki/File:Denormalized_numbers_on_a_line.svg




Gruß



_______________________________________________
Talk-de mailing list
[email protected]
https://lists.openstreetmap.org/listinfo/talk-de

Antwort per Email an