Float сравнительное решение для Python 2.6 - PullRequest
0 голосов
/ 25 января 2019

Я делаю простое сравнение между строковым значением и значениями с плавающей запятой minValue и maxValue, чтобы проверить, находится ли значение за пределами определенного диапазона

if float(value) < minValue or float(value) > maxValue:
    # show error and exit

Работает нормально, если значения и minValue не совпадают. Поэтому, когда value = -1.234 и minValue = -1.234, он входит в оператор if, потому что по какой-то причине -1.234 < -1.234 оценивается как True.

Мой обходной путь - использовать десятичную

if Decimal(value) < Decimal(str(minValue)) or Decimal(str(value) > Decimal(maxValue):
    # show error and exit

Но Decimal(str(minValue)) выглядит немного грязно, поэтому мне интересно, есть ли лучший способ сравнить два числа с плавающей запятой, которые не потерпят неудачу, если они имеют одинаковое значение, без необходимости сначала выполнять преобразование с плавающей запятой в строку в десятичное.

EDIT

value происходит из CSV-файла, поэтому здесь нет усечения. То, что вы видите, это то, что вы получаете. minValue, однако, является результатом полиномиальной функции, но я не верю, что там есть какое-либо усечение или округление.

Вот функция для вычисления minValue

f = numpy.poly1d(coefficients)
x = range(int(low), int(high), 1)
y = f(x)
minValue = min(y)
maxValue = max(y)

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Обратите внимание, что в общем случае это невозможно решить без Decimal;Во многих вычислениях математика с плавающей запятой является неточной, и то, что логически должно прийти к -1.234, может легко стать -1.2339999999999998 или -1.2340000000000002 (только для иллюстрации ваш компьютер может отличаться, но это самые близкие значения к -1.234 налюбая сторона на моей машине, которая не округляется до канонического представления -1.234, ваш расчет может быть таким близким, или он может быть немного больше, но, вероятно, ошибка все равно будет меньше 0.00000000001).

Тем не менее, если вам с уверенностью известно, что вашим значениям никогда не потребуется больше, чем X десятичных знаков точности, вы часто можете избежать использования более быстрого float через функция round , чтобы гарантировать, что ваши значения действительно являются наиболее близким представимым значением, чем они должны быть логически.Поскольку кажется, что minValue и maxValue вычисляются один раз вперед, просто измените последний шаг, чтобы округлить их, например:

minValue = round(min(y), 3)
maxValue = round(max(y), 3)

, который удаляет любую ложную избыточную точность.Черт возьми, если вы не уверены, насколько точным вы должны быть, просто удвойте свое предположение;неточность, которую вы, вероятно, увидите в большинстве случаев, обычно превышает 10 цифр после десятичной точки, поэтому, если вам кажется, что вам нужны только три цифры, но вы беспокоитесь, вы все равно можете удалить действительные данные (например, возможно, у вас естьделение на 8, которое может оставить дополнительный, действительный 125 в конце), просто подняться немного больше, округлив до 6 или даже 9 десятичных знаков.

Аналогично,измените код, который выполняет сравнение, чтобы также нормализовать value, например:

if round(float(value), 3) < minValue or round(float(value), 3) > maxValue:

или даже лучше (избегая дублирования кода преобразования):

if not minValue <= round(float(value), 3) <= maxValue:

, что дает преимуществооператоров цепочки сравнения Python (это эквивалентно вводу if not (minValue <= round(float(value), 3) and round(float(value), 3) <= maxValue):, за исключением того, что round(float(value), 3) вычисляется только один раз).

0 голосов
/ 25 января 2019

Причина, по которой он не работает, потому что -1.234 не больше или меньше -1.234. -1.234 > 1.234 ложно и -1.234 < 1.234 также ложно. Если вы также хотите, чтобы это было правдой, если они равны, вам нужно будет использовать => или =<, что означает «больше или равно»

>>> value=-1.234
>>> maxValue=-1.234
>>> minValue=-1.234
>>> float(value)
-1.234
>>> float(value) < minValue or float(value) > maxValue
False
>>> float(value) <= minValue or float(value) >= maxValue
True
...