33

How can I take a float variable, and control how far out the float goes without round()? For example.

w = float(1.678)

I want to take x and make the following variables out of it.

x = 1.67
y = 1.6
z = 1

If I use the respective round methods:

x = round(w, 2) # With round I get 1.68 
y = round(y, 1) # With round I get 1.7
z = round(z, 0) # With round I get 2.0

It's going to round and alter the numbers to the point where there no use to me. I understand this is the point of round and its working properly. How would I go about getting the information that I need in the x,y,z variables and still be able to use them in other equations in a float format?

Mike Laren
  • 8,028
  • 17
  • 51
  • 70
Branzol
  • 343
  • 1
  • 3
  • 7

7 Answers7

52

You can do:

def truncate(f, n):
    return math.floor(f * 10 ** n) / 10 ** n

testing:

>>> f=1.923328437452
>>> [truncate(f, n) for n in range(7)]
[1.0, 1.9, 1.92, 1.923, 1.9233, 1.92332, 1.923328]
8

A super simple solution is to use strings

x = float (str (w)[:-1])
y = float (str (w)[:-2])
z = float (str (w)[:-3])

Any of the floating point library solutions would require you dodge some rounding, and using floor/powers of 10 to pick out the decimals can get a little hairy by comparison to the above.

WakkaDojo
  • 431
  • 3
  • 7
  • Thank you, I'm going to play around with this one. I figured formatting it would create issues as it becomes a string instead of a float? – Branzol Mar 25 '15 at 03:18
  • 1
    I see what you're saying -- Python's floating point arithmetic can sometimes create long strings. But in that case you'd have issues picking out the decimals anyway. A sanity check could instead be iterating from the beginning instead of the end: x = float (str (w)[:4] (etc) – WakkaDojo Mar 25 '15 at 03:22
6

Integers are faster to manipulate than floats/doubles which are faster than strings. In this case, I tried to get time with both approach :

  timeit.timeit(stmt = "float(str(math.pi)[:12])", setup = "import math", number = 1000000)

~1.1929605630000424

for :

timeit.timeit(stmt = "math.floor(math.pi * 10 ** 10) / 10 ** 10", setup = "import math", number = 1000000)

~0.3455968870000561

So it's safe to use math.floor rather than string operation on it.

Raj
  • 75
  • 1
  • 7
2

If you just need to control the precision in format

pi = 3.14159265
format(pi, '.3f') #print 3.142 # 3 precision after the decimal point
format(pi, '.1f') #print 3.1
format(pi, '.10f') #print 3.1415926500, more precision than the original

If you need to control the precision in floating point arithmetic

import decimal
decimal.getcontext().prec=4 #4 precision in total
pi = decimal.Decimal(3.14159265)
pi**2 #print Decimal('9.870') whereas '3.142 squared' would be off

--edit--

Without "rounding", thus truncating the number

import decimal
from decimal import ROUND_DOWN
decimal.getcontext().prec=4
pi*1 #print Decimal('3.142')

decimal.getcontext().rounding = ROUND_DOWN
pi*1 #print Decimal('3.141')
SYK
  • 644
  • 6
  • 17
  • 1
    The format section of your example rounds the numbers when I switch pi to the value in my example. I did learn a ton from this example on other things, but the rounding is what I was trying to stay away from, I needed non rounded numbers. – Branzol Mar 25 '15 at 03:16
  • @Branzol . You're still rounding, just with a different rule. Sorry I didn't see it clearly that you're "rounding" 1.67 as 1.6 and then 1. – SYK Mar 25 '15 at 04:24
  • 2
    Why must you `from decimal import ROUND_DOWN` if you've already `import decimal`? – Unknow0059 Nov 21 '20 at 20:54
  • Use pi.normalize() instead of pi*1 – Sam Apr 03 '22 at 04:39
1

I think the easiest answer is :

from math import trunc

w = 1.678
x = trunc(w * 100) / 100
y = trunc(w * 10) / 10
z = trunc(w)
Hessam
  • 19
  • 2
  • The `trunc()` is equivalent to the `floor()` function for a positive float (see [documentation](https://docs.python.org/3/library/math.html#math.trunc)), so your answer is actually the same as the accepted answer. – AlexK Jun 17 '22 at 04:13
  • 1
    @AlexK it isn't really the same answer, since `trunc()` works for both positive and negative float, but the accepted answer only works 100% of the time without rounding for positive float. See [this comment under the accepted answer mentioning the same thing](https://stackoverflow.com/questions/29246455/python-setting-decimal-place-range-without-rounding#comment93080988_29257837). – Nordine Lotfi Jan 15 '23 at 08:54
0

also this:

>>> f = 1.678
>>> n = 2
>>> int(f * 10 ** n) / 10 ** n
1.67
gtlee
  • 86
  • 1
  • 3
-1

Easiest way to get integer:

series_col.round(2).apply(lambda x: float(str(x).split(".",1)[0]))

Onkar
  • 1
  • 2
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 28 '22 at 16:23