2011-01-07 6 views
1

Ich habe eine Liste von Gleitkommazahlen, die x-und y-Koordinaten von Punkten darstellen.Nummer Approximation in Python

(-379.99418604651157, 47.517234218543351, 0.0) #representing point x 

Eine Kante enthält zwei solche Zahlen.

Ich würde gerne einen Graph Traversal Algorithmus, wie Dijkstra verwenden, aber die Verwendung von Gleitkommazahlen wie die oben genannten nicht helfen. Was ich suche eigentlich für einen Weg, um die Zahl der Annäherung:

(-37*.*, 4*.*, 0.0) 

gibt es eine Python-Funktion, die das tut?

+0

von fpformat import fix – Ant

+0

@Ant: 'fix()' gibt eine Zeichenfolge zurück. Darüber hinaus ist "fpformat" seit Pyhon 2.6 veraltet und wurde in Python 3 entfernt. –

+0

Ich wusste, dass fix eine Zeichenfolge zurückgibt, aber nicht, dass sie veraltet ist. Danke – Ant

Antwort

1

Wie so?

>>> x, y, z = (-379.99418604651157, 47.517234218543351, 0.0) 
>>> abs(x - -370) < 10 
True 
>>> abs(y - 40) < 10 
True 
+0

Nein, betrachten 'x, y, z = (-3000, -3000, 0)'. Sie bestehen auch Ihren Test. Sie müssen 'abs (x - -370) <10 'verwenden. Das wird -360 bis -380 akzeptieren. – Oddthinking

+0

Richtig du bist. Aktualisiert. –

+0

für weitere Abstraktion. Wie kann ich die ersten zwei Ziffern in x lesen? – user228137

2

"... die Verwendung von Gleitkommazahlen wie die oben genannten helfen nicht ..." - warum nicht? Ich erinnere mich nicht an Ganzzahlen als Voraussetzung für Dijkstra. Geht es dir nicht um die Länge der Kante? Das ist eher eine Gleitkommazahl, selbst wenn die Endpunkte in ganzzahligen Werten ausgedrückt sind.

Ich zitiere aus Steve Skiena des "Algorithm Design Manual":

Dijkstra-Algorithmus geht in einer Reihe von Runden, wobei jede Runde den kürzesten Weg von s zu einigen neuen Vertex etabliert. Insbesondere x wird, um den Scheitelpunkt, die minimiert dist (s, vi) + w (vi, x) über alle unvollendeten 1 < = i = n ... <

Entfernung - keine Erwähnung ganze Zahl.

+0

Das Problem ist in den Punkten der Knoten und Kanten, die nicht verbunden sind. Diese Punkte werden von einem Benutzer erzeugt, der einfach eine Linie zeichnet und (s) er denkt, dass dies eine Kante ist. Damit der Algorithmus funktioniert, müssen die Kanten verbunden/geschnitten sein, aber wenn eine Kante am Knoten -379.99418604651157, 47.517234218543351, 0.0 beginnt und eine andere bei -379.993, 47.5171.0.0 beginnt, obwohl sie scheinbar auf der Karte verbunden erscheinen, Aufgrund ihrer Positionsdetails sind sie keine Kante in einem Graphen. Dijkstra untersucht die Kanten, die mit einem Knoten verbunden sind. Ich versuche, einen Radius um diese Werte zu setzen. – user228137

+2

Sie sollten mit Epsilonen, absoluten und relativen Fehlern umgehen, wenn Sie Fließkommazahlen verwenden. Sie können die Gleichheit nicht überprüfen. Sie müssen die Nähe innerhalb einer Fehlergrenze prüfen. Nichts davon hat etwas mit Dijkstra zu tun; Sie müssen die Konnektivität Ihres Graphen überprüfen, bevor Sie mit den Berechnungen beginnen. Es ist ein Vorverarbeitungsschritt, wenn Sie das Diagramm einlesen. Seien Sie vorsichtig, dass das Epsilon, das Sie wählen, groß genug ist, um Fehler zu schließen, aber nicht so groß, dass Sie zwei Punkte entdecken und ausblenden, die eindeutig sein sollten. – duffymo

0

Ich bin mir nicht sicher, was das Problem mit den Gleitkommazahlen ist, aber es gibt mehrere Möglichkeiten, wie Sie Ihre Werte annähern können. Wenn Sie sie nur runden möchten, können Sie math.ceil(), math.floor() und math.trunc() verwenden.

Wenn Sie tatsächlich die Genauigkeit im Auge behalten möchten, gibt es eine Reihe von Multi-Precision-Mathematik-Bibliotheken listed on the wiki, die nützlich sein könnten.

0

Ich nehme an, dass Sie die Zahl approximieren möchten, damit Sie Ihren Algorithmus visuell leicht verstehen können, während Djikstra keine Beschränkung auf die Koordinate des Knotens darstellt, sondern nur an den Kosten interessiert ist von Kanten).

Eine einfache Funktion ungefähre Zahlen:

>>> import math 
>>> def approximate(value, places = 0): 
...  factor = 10. ** places 
...  return factor * math.trunc(value/factor) 
>>> p = (-379.99418604651157, 47.517234218543351, 0.0) 
>>> print [ approximate(x, 1) for x in p ] 
[-370.0, 40.0, 0.0] 
1

Angesichts Ihrer Vektor

(-379.99418604651157, 47.517234218543351, 0.0) #representing point x 

Der einfachste Weg Runden auszuführen, wie Sie funktioniert wahrscheinlich das Dezimal-Modul verwenden würde erwarten wäre: http://docs.python.org/library/decimal.html .

from decimal import Decimal: 
point = (-379.99418604651157, 47.517234218543351, 0.0) #representing point x 
converted = [Decimal(str(x)) for x in point] 

Dann eine Annäherung zu erhalten, können Sie den Quantisierungswert-Methode verwenden:

>>> converted[0].quantize(Decimal('.0001'), rounding="ROUND_DOWN") 
Decimal("-379.9941") 

Dieser Ansatz hat den Vorteil der in der Fähigkeit gebaut, um Rundungsfehler zu vermeiden. Hoffentlich ist das hilfreich.

Edit:

Nachdem Sie Ihren Kommentar zu sehen, es sieht aus wie Sie zu sehen, sind versuchen, wenn zwei Punkte nahe zueinander sind. Diese Funktionen könnten tun, was Sie wollen:

def roundable(a,b): 
    """Returns true if a can be rounded to b at any precision""" 
    a = Decimal(str(a)) 
    b = Decimal(str(b)) 
    return a.quantize(b) == b 

def close(point_1, point_2): 
    for a,b in zip(point_1, point_2): 
     if not (roundable(a,b) or roundable(b,a)): 
      return False 
    return True 

Ich weiß nicht, ob dies ist besser als ein Epsilon-Ansatz, aber es ist ziemlich einfach zu implementieren.

Verwandte Themen