Как я могу обрезать число с плавающей точкой чуть ниже предела? - PullRequest
6 голосов
/ 23 февраля 2012

Такие функции, как numpy.random.uniform(), возвращают значения с плавающей запятой между двумя границами, включая первую, но , исключая верхнюю.То есть numpy.random.uniform(0,1) может дать 0, но никогда не приведет к 1.

Я беру такие числа и обрабатываю их с помощью функции, которая иногда возвращает результаты вне диапазона.Я могу использовать numpy.clip(), чтобы обрезать значения за пределами диапазона до 0-1, но, к сожалению, этот предел составляет включительно от верхнего числа.

Как сделатьЯ указываю "число бесконечно меньше, чем 1" в Python?

Ответы [ 3 ]

7 голосов
/ 23 февраля 2012

Ну, если вы используете numpy, вы можете просто использовать numpy.nextafter :

>>> import numpy
>>> numpy.nextafter(1, 0)
0.99999999999999989

Обратите внимание, что (по крайней мере для меня):

>>> import sys
>>> 1-sys.float_info.epsilon
0.9999999999999998
>>> numpy.nextafter(1, 0) - (1-sys.float_info.epsilon)
1.1102230246251565e-16
>>> numpy.nextafter(1, 0) > (1-sys.float_info.epsilon)
True

Кстати, во второй точке @Robert Kern, которая иногда random.uniform будет включать верхнюю границу для некоторых входных данных, отличных от (0, 1):

>>> import random, numpy
>>> numpy.nextafter(0,1)
4.9406564584124654e-324
>>> random.uniform(0, numpy.nextafter(0,1))
0.0
>>> random.uniform(0, numpy.nextafter(0,1))
0.0
>>> random.uniform(0, numpy.nextafter(0,1))
4.9406564584124654e-324

[Я разделяюобщее ощущение, что, возможно, есть лучший способ решения этой проблемы.]

3 голосов
/ 23 февраля 2012

Python sys предоставляет структуру float_info с атрибутом epsilon и определяется как

разница между 1 и наименьшим значением больше 1, которое представляется как число с плавающей запятой

Так что я бы предположил что-то вроде

def clip(num):
    if(num >= 1):
        return 1 - sys.float_info.epsilon
    return num

должен сделать свое дело. Хотя, как правило, это плохо, и, вероятно, существует масса причин, по которым вам никогда не следует пытаться это делать.

РЕДАКТИРОВАТЬ Я только что заметил одну такую ​​причину - реализация. Хотя CPython делает то, что вы ожидаете, мой первый выбор - это IronPython, который не (хотя это ошибка). Будьте предупреждены!

2 голосов
/ 23 февраля 2012

В большинстве практических случаев вам не нужно быть бесконечно меньше, вы можете приблизить его. Поэтому для вашего примера я бы использовал 0,9999999 вместо 1,0.

...