2013-10-25 2 views
4

Это очень простой вопрос. Препятствует означают следующее:Python - Flooring floats

>>> x = 1.2876 

Теперь round имеет этот большой необязательный второй параметр, который будет круглый в этом знаке после запятой:

>>> round(x,3) 
1.288 

мне было интересно, если есть простой способ округлить число , math.floor(x,3) возвращает ошибку, а не 1.287

+3

"округлением вниз" вы имеете в виду по отношению к 0 или к отрицательной бесконечности? Это имеет значение для отрицательных чисел (например, «floor (-3.1) == -4.0'). –

+0

Кстати, это как раз то, как круглый ведет себя, так как .876 ближе к 0,88, чем 0,87. Почему вы хотите, чтобы он пола? – aIKid

+0

Интересный вопрос. – aIKid

ответ

2

Это что-то, что появилось в моем сознании. Почему бы нам не преобразовать его в строку, а потом поместить его?

import math 
def floor_float(x, index): 
    sx = str(x) 
    sx = sx[:index]+str(math.floor(float(sx[index]+"."+sx[index+1]))) 
    return float(sx) 

Немного преимущество состоит в том, что это более representating ошибки доказательства, что более точно в representating числа (так как это строка):

>>> floor_float(10.8976540981, 8) 
10.897654 

Это может быть, не самым лучшим вещего решения, хотя. . Но это работает достаточно хорошо :)

Update

В Python 2.x, math.floor Ретур ns float вместо integer. Для того, чтобы сделать эту работу вы будете конвертировать результат, в целое число:

sx = sx[:index]+str(int(math.floor(float(sx[index]+"."+sx[index+1])))) 

UPDATE2

Чтобы быть честным, код выше, в основном нонсенс, и слишком сложно;)

Так как это пол, вы можете просто обрезать строку, и плывут обратно:

def floor_float(x, i): 
    return float(str(x)[:i]) 
+0

Да, это позволяет избежать проблем с плавающей запятой! Я не собираюсь использовать это решение, потому что мне захочется, чтобы число отображалось просто после десятичной, но я думаю, что поеду с этой техникой –

+0

@aIKid, вы редактировали этот код? Это не работает, как показано сейчас; например, 'floor_float (10.8976540981, 8)' вызывает 'ValueError: недействительный литерал для float(): 10.897654.0' на' return' stmt. –

+0

Вы используете python 2.x? Я просто заметил, что там тоже не работает. Подожди. – aIKid

2

Всегда есть floor(x*10**3)*10**-3.

+2

Примечание: вместо этого численно лучше делить на 10 ** 3. Одна ошибка округления вместо двух (10 ** - 3 страдает собственной ошибкой округления, а затем умножается на то, что вносит еще одну ошибку округления). И быстрее делать пол (x * 1e3)/1e3 ;-) –

+1

@TimPeters подтверждено. если x имеет пять знаков после запятой, 'math.floor (x * 10 ** 5) * 10 ** - 5' приводит к ' 1.2876500000000002' – aIKid

+2

@aIKid, это своего рода «мелкий сюрприз», о котором я говорил в своем собственный ответ. Метод _any_ невозможно избежать во всех случаях - бинарные поплавки приближают только десятичные значения. –

1
def roundDown(num, places): 
    return int(num*(10**places))/float(10**places) 
3

Это может быть простой, если «округлением вниз» вы имеете в виду «в сторону минус бесконечности» (как floor() делает):

>>> x = 1.2876 
>>> x - x % .001 
1.287 
>>> x = -1.1111 
>>> x - x % .001 
-1.112 

Это склонным к большому количеству мелких сюрпризов, хотя, из-за этого большинство десятичных значений не могут быть точно представлены как двоичные значения с плавающей запятой. Если вас это беспокоит, сделайте что-то подобное с значениями decimal.Decimal.

2

другой подход, опираясь на decimal Более сложные средства модуля. Как встроено round(), это также поддерживает отрицательную «цифру»:

>>> round(1234.5, -1) # builtin behavior for negative `ndigits` 
1230.0 
>>> round(1234.5, -2) 
1200.0 
>>> round(1234.5, -3) 
1000.0 

и вы можете использовать любого из 8 режимов округления, определенных в decimal (!).

from decimal import ROUND_DOWN 
def rfloat(x, ndigits=0, rounding=ROUND_DOWN): 
    from decimal import Decimal as D 
    proto = D("1e%d" % -ndigits) 
    return float(D(str(x)).quantize(proto, rounding)) 

Пример:

for i in range(-4, 6): 
    print i, "->", rfloat(-55555.55555, i) 

производит:

-4 -> -50000.0 
-3 -> -55000.0 
-2 -> -55500.0 
-1 -> -55550.0 
0 -> -55555.0 
1 -> -55555.5 
2 -> -55555.55 
3 -> -55555.555 
4 -> -55555.5555 
5 -> -55555.55555 

Попытка разобрать строки вместо на свой страх и риск ;-)