2011-01-07 3 views
1

У меня есть список чисел с плавающей запятой, которые представляют координаты x и y точек.Числовое приближение в python

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

край содержит два таких числа.

Я бы хотел использовать алгоритм обхода графика, такой как dijkstra, но использование чисел с плавающей запятой, таких как приведенные выше, не помогает. То, что я на самом деле ищу способ аппроксимации этих чисел:

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

есть функция питона, что делает это?

+0

from fpformat import fix – Ant

+0

@Ant: 'fix()' возвращает строку. Кроме того, 'fpformat' устарел с Pyhon 2.6 и удален в Python 3. –

+0

Я знал, что исправление возвращает строку, но не то, что она устарела; спасибо – Ant

ответ

1

Как так?

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

Нет, рассмотрим 'x, y, z = (-3000, -3000, 0)'. Они также проходят ваш тест. Вам нужно использовать 'abs (x - -370) <10'. Это будет принимать от -360 до -380. – Oddthinking

+0

Вы правы. Обновлено. –

+0

для дальнейшей абстракции. Как я могу прочитать первые две цифры в x? – user228137

2

«... с использованием чисел с плавающей запятой, таких как приведенные выше, не помогают ...» - почему бы и нет? Я не помню целых чисел как требование для Дейкстры. Разве вы не связаны с длиной края? Скорее всего, это число с плавающей запятой, даже если конечные точки выражаются целыми значениями.

Я цитирую Стивен Скиена в «Алгоритм Руководство по проектированию»:

алгоритм переходит Дейкстры в серии раундов , где каждый раунд устанавливает кратчайший путь от с до некоторой новой вершины. В частности, х является вершиной, которая сводит к минимуму DIST (с, VI) + W (VI, х) по всем незаконченным 1 < = я < = п ...

Расстояния - нет упоминания о целое число.

+0

Проблема заключается в том, что узлы и ребра не связаны. Эти точки генерируются пользователем, который просто рисует линию, и (а) он считает, что это край. Для того чтобы алгоритм работал, ребра должны быть связаны/пересекаться, но когда есть ребро, которое начинается с узла -379.99418604651157, 47.517234218543351, 0.0 и другое, которое начинается с -379.993, 47.5171, 0.0, хотя, похоже, они отображаются на карте, из-за их деталей позиции они не являются краем графика. Dijkstra исследует края, связанные с узлом. Я пытаюсь установить радиус вокруг этих значений. – user228137

+2

Вы должны иметь дело с эпсилонсами, абсолютными и относительными ошибками всякий раз, когда вы используете числа с плавающей запятой. Вы не можете проверить равенство; вам нужно проверить близость в пределах некоторой ошибки. Ничего из этого не имеет никакого отношения к Дейкстре; вам нужно проверить подключение вашего графика до начала вычислений. Это шаг предварительной обработки, когда вы читаете на графике. Просто будьте осторожны, чтобы выбранный вами epilon был достаточно большим, чтобы закрыть ошибки, но не настолько большой, чтобы вы обнаруживали и сворачивали две точки, которые должны быть различны. – duffymo

0

Я не уверен, в чем проблема с числами с плавающей запятой, но есть несколько способов аппроксимировать ваши значения. Если вы просто хотите их окружить, вы можете использовать math.ceil(), math.floor() и math.trunc().

Если вы действительно хотите отслеживать точность, есть куча многоточечных математических библиотек listed on the wiki, которые могут быть полезны.

0

Я предполагаю, что вы хотите приблизить число, чтобы визуально легко понять, что вы алгоритм, вступая в него (поскольку Djikstra не ограничивает координаты узла, на самом деле его интересует только стоимость ребер).

Простая функция приблизительным чисел:

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

Учитывая ваш вектор

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

Самый простой способ выполнить округление, который работает, как и следовало ожидать, вероятно, будет использовать десятичную модуль: 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] 

Затем, чтобы получить приближение, вы можете использовать метод квантования:

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

Этот подход имеет преимущество встроенной возможности избежать ошибок округления. Надеюсь, это полезно.

Edit:

Осмотрев свой комментарий, это выглядит, как вы пытаетесь увидеть, если две точки находятся близко друг к другу. Эти функции могут делать то, что вы хотите:

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 

Я не знаю, если это лучше, чем эпсилон подход, но это довольно просто реализовать.