rounding float up $.01 in python - python

I am working on a program that stores numbers as floats which I eventually write to a file as currency. I am currently using the round() function to round it to 2 decimals, but the business area would like me to round to the next penny no matter what the third decimal is. For example:
x = 39.142
In this case I am trying to get x to round up to 39.15. Obviously when I do the round function I get 39.14...
>>> round(x, 2)
39.14
Is there a way I can always round up to the next penny? I should mention that the numbers I am dealing with are printed to the file as currency.

Using the decimal module:
import decimal
D = decimal.Decimal
cent = D('0.01')
x = D('39.142')
print(x.quantize(cent,rounding=decimal.ROUND_UP))
# 39.15
Decimals have many options for rounding. The options and their meanings can be found here.

if you want to write it in cents, you could use int(x*100+.5) to get cents integer from float dollars.

Very late to this, but in case anyone wants a simple one-liner in Python 3:
import math
x_rounded = math.ceil(x*100) / 100

Related

Python increment float by smallest step possible predetermined by its number of decimals

I've been searching around for hours and I can't find a simple way of accomplishing the following.
Value 1 = 0.00531
Value 2 = 0.051959
Value 3 = 0.0067123
I want to increment each value by its smallest decimal point (however, the number must maintain the exact number of decimal points as it started with and the number of decimals varies with each value, hence my trouble).
Value 1 should be: 0.00532
Value 2 should be: 0.051960
Value 3 should be: 0.0067124
Does anyone know of a simple way of accomplishing the above in a function that can still handle any number of decimals?
Thanks.
Have you looked at the standard module decimal?
It circumvents the floating point behaviour.
Just to illustrate what can be done.
import decimal
my_number = '0.00531'
mnd = decimal.Decimal(my_number)
print(mnd)
mnt = mnd.as_tuple()
print(mnt)
mnt_digit_new = mnt.digits[:-1] + (mnt.digits[-1]+1,)
dec_incr = decimal.DecimalTuple(mnt.sign, mnt_digit_new, mnt.exponent)
print(dec_incr)
incremented = decimal.Decimal(dec_incr)
print(incremented)
prints
0.00531
DecimalTuple(sign=0, digits=(5, 3, 1), exponent=-5)
DecimalTuple(sign=0, digits=(5, 3, 2), exponent=-5)
0.00532
or a full version (after edit also carries any digit, so it also works on '0.199')...
from decimal import Decimal, getcontext
def add_one_at_last_digit(input_string):
dec = Decimal(input_string)
getcontext().prec = len(dec.as_tuple().digits)
return dec.next_plus()
for i in ('0.00531', '0.051959', '0.0067123', '1', '0.05199'):
print(add_one_at_last_digit(i))
that prints
0.00532
0.051960
0.0067124
2
0.05200
As the other commenters have noted: You should not operate with floats because a given number 0.1234 is converted into an internal representation and you cannot further process it the way you want. This is deliberately vaguely formulated. Floating points is a subject for itself. This article explains the topic very well and is a good primer on the topic.
That said, what you could do instead is to have the input as strings (e.g. do not convert it to float when reading from input). Then you could do this:
from decimal import Decimal
def add_one(v):
after_comma = Decimal(v).as_tuple()[-1]*-1
add = Decimal(1) / Decimal(10**after_comma)
return Decimal(v) + add
if __name__ == '__main__':
print(add_one("0.00531"))
print(add_one("0.051959"))
print(add_one("0.0067123"))
print(add_one("1"))
This prints
0.00532
0.051960
0.0067124
2
Update:
If you need to operate on floats, you could try to use a fuzzy logic to come to a close presentation. decimal offers a normalize function which lets you downgrade the precision of the decimal representation so that it matches the original number:
from decimal import Decimal, Context
def add_one_float(v):
v_normalized = Decimal(v).normalize(Context(prec=16))
after_comma = v_normalized.as_tuple()[-1]*-1
add = Decimal(1) / Decimal(10**after_comma)
return Decimal(v_normalized) + add
But please note that the precision of 16 is purely experimental, you need to play with it to see if it yields the desired results. If you need correct results, you cannot take this path.

Python, How to round up to maximum precision

It's quite a simple question actually, let's say i have this number 1.499998499999999e-98, now if i wanted to round it up to ~1.5e-98 how would i go about it? I tried the round() but it gives me 0.0 which is kind of useless for what i'm working on.
One (kinda 'hacky') way would be to format the number as a string and convert back to float:
>>> x = 1.499998499999999e-98
>>> "%.2e" % x
'1.50e-98'
>>> float("%.2e" % x)
1.5e-98
Other than using round, this will round to significant digits, not "absolute" number of digits.
You can specify the number of digits that you want to round to (see the documentation), and also read the note about rounding being surprising.
Numpy may give you a little more control over rounding.

Rounding Off function to given decimal without using round function

I am trying to write a function to round a floating point number up to n decimal places. The function can take one or two arguments. If there is only one argument the number should be rounded to two decimal places.
This is where I have gotten so far:
def roundno(num,point=2):
import math
x=1*(math.pow(10,-point))
round=0
while (num>x):
while(num>0):
round+=num/10
num=num/10
round*=10
round+=num/10
num=num/10
round*=0.1
return round
I am getting infinity as the output, every time... Where did I go wrong?
I can't see how your algorithm is supposed to round numbers. I guess a similar strategy could work, but you'd need a subtraction in there somewhere...
One way to do this would be to convert the argument to a string, adjust the number of digits after the decimal point, and then convert the string back to a float, but I suspect that your teacher would not like that solution. :)
Here's a simple way to do rounding arithmetically:
def roundno(num, point=2):
scale = 10.0 ** point
return int(num * scale) / scale
data = [123, 12.34, 1.234, 9.8765, 98.76543]
for n in data:
print n, roundno(n), roundno(n, 3)
output
123 123.0 123.0
12.34 12.34 12.34
1.234 1.23 1.234
9.8765 9.87 9.876
98.76543 98.76 98.765
This simply drops unwanted digits, but it's not hard to modify it to round up or off (your question isn't clear on exactly what type of rounding you want).
Note that this function doesn't check the point argument. It really should check that it's a non-negative integer and raise ValueError with an appropriate error message otherwise.

Simple way to round floats when printing

I am working on a project where it has to take user inputs and do calculations.
What I am aiming for is the print to appear as
Inform the customer they saved 0.71 today
Not
Inform the customer they saved 0.7105000000000001 today
Is there something I can put into the same line of code with the print function to have it be rounded? Or do I have to modify each variable.
I can post my code if requested.
You can use the builtin round() function and float formatting:
>>> print "{0:0.2f}".format(round(x, 2))
0.71
Some Notes:
{0.2f} will format a float to 2 decimal places.
round(x, 2) will round up to 2 decimal places.
Side Note: round() is really necessary IHMO if you want to "round" the number before "display". It really depends on what you're doing!
round() is return the floating point value number rounded to ndigits digits after the decimal point. which takes as first argument the number and the second argument is the precision
no = 0.7105000000000001
print round(no, 2)
second solution:
print "%.2f" % 0.7105000000000001
use decimal instead of round()
from decimal import *
print(round(8.494,2)) # 8.49
print(round(8.495,2)) # 8.49
print(round(8.496,2)) # 8.5
print(Decimal('8.494').quantize(Decimal('.01'), rounding=ROUND_HALF_UP)) #8.49
print(Decimal('8.495').quantize(Decimal('.01'), rounding=ROUND_HALF_UP)) #8.50
print(Decimal('8.496').quantize(Decimal('.01'), rounding=ROUND_HALF_UP)) #8.50

Python, infinite floats?

What I wanted to do:
Paradox: Suppose Peter Parker were running to catch a bus. To reach it, he’d first need to get halfway there. Before that, he’d need to get a quarter of the way there……before a quarter, an eighth; before an eighth, a 16th; and so on. Since the distance can be halved infinitely, he’d be trying to complete an infinite number of tasks… WHICH WOULD BE LOGICALLY IMPOSSIBLE!
I tried to to resolve this paradox using Python
I have some questions:
How can I get a number to have no limitations with decimals? Python limits the numbers of decimals, I think to 12, How to make that number infinite?
Aparrently there is no way to make the float decimals infinite, the closest I could get was using this
from decimal import Decimal
Is this the correct way of asking the user for an input in numbers?
Code modified
from decimal import Decimal
def infinite_loop():
x = 0;
number = Decimal(raw_input())
while x != number:
x = x + number
number = number/2
print x
infinite_loop()
What you ask is impossible. There are no "infinite precision" floating point values in the real world of finite computing systems. If there were, a single floating point value could consume all of the system's resources. pi * d? Ooops!! pi is infinite. There goes the system!
What you can do, however, is get arbitrary precision decimal values. They're still finite, but you can choose how much precision you want (and are willing to pay for). E.g.:
>>> from decimal import Decimal
>>> x = Decimal('1.' + '0' * 200)
>>> x
Decimal('1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')
Now you have 200 digits of precision. Not enough? Go 400. 800. However many you like. As long as that's a finite, practical value.
If you want "infinite" precision (e.g. a decimal number that be extended as far as you have memory for), either use Python's builtin module Decimal or for more heavy computation, mpmath:
import mpmath as mp
mp.mp.dps = 100
print mp.sqrt(mp.mpf(2))
>> 1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573

Categories