Python and percentages - python

Is there a proper way to handle percentages in Python?
For example, how to handle the value 0.01 and make it displayed as 1%

You can also use str.format()
percentage = 0.01
print "{0:.0f}%".format(percentage * 100)
1%
percentage = 0.0142
print "{0:.0f}%".format(percentage * 100)
1%
percentage = 0.0142
print "{0:.1f}%".format(percentage * 100)
1.4%

Multiply by a hundred then convert to int
>>> int(0.01 * 100)
1
As a function
def dec_to_pct(i):
return int(i*100)
>>> dec_to_pct(0.01)
1
>>> dec_to_pct(0.07)
7
>>> dec_to_pct(0.42)
42
Note
If you'd like to preserve remaining decimals, just leave off the conversion to int, e.g.
>>> 0.4273 * 100
42.73 # percent

Related

how to output the difference of two floats as an interger in python

is there any way to output the difference between two float numbers as an integer
below is three examples of the float values provided for script, my goal is to output the difference between these values as an integer , in the first example i should get 2 where num_two - num_one equals 0.000002 but i don't want the zeros as they don't matter i can do it with string format but i have no way of telling how big the number is or how many zeros it has
## example 1
num_one = 0.000012
num_two = 0.000014
## example 2
num_0ne = 0.0123
num_tw0 = 0.013
## example 3
num_1 = 23.32
num_2 = 23.234
print (float(num_2) - float(num_1))
## this should output 86 as an integer
Beware of floats (see https://en.wikipedia.org/wiki/IEEE_754):
>>> 23.32 - 23.234
0.08599999999999852
You need exact precision. Use the decimal module:
>>> from decimal import Decimal
>>> n1 = Decimal("23.32")
>>> n2 = Decimal("23.234")
>>> n1, n2
(Decimal('23.32'), Decimal('23.234'))
>>> d = abs(n1-n2)
>>> d
Decimal('0.086')
Now, just shift the decimal point right (that is * 10) until there is no fractional part left (d % 1 == 0):
>>> while d % 1:
... d *= 10
(Don't be afraid, the loop will stop because you can't have more decimal levels than decimal.getcontext().prec at the beginning and the decimal level decrease on each iteration).
You get the expected result:
>>> d
Decimal('86.000')
>>> int(d)
86

Format print value as percentage in python

I have this code:
if SPEED <= 0.0129:
seqSpeed = (SPEED / 100.0) * 15.5
print("Speed: {:1.0%}".format(seqSpeed))
Instead of showing Speed: 20%
It shows Speed: 1%%%
What can I do to fix it?
The % specifier multiplies the value by a hundred then acts as if you'd used the f specifier.
Since your maximum SPEED here is 0.0129 (as per the if statement), your formula (SPEED / 100.0) * 15.5 will generate, at most, 0.0019995. The % specifier will then turn that into 0.19995, which is only about 0.2%.
If you're expecting it to give you 20%, you need to get rid of the / 100.0 bit from your formula. That way, you'll end up with 0.19995, the % specifier will change that to 19.995, and you should then get 20% by virtue of the fact you're using 1.0 as the width specification, as per the following transcript:
>>> SPEED = 0.0129
>>> seqSpeed = SPEED * 15.5
>>> print("Speed: {:1.0%}".format(seqSpeed))
Speed: 20%
Use f-strings instead:
if SPEED <= 0.0129:
seqSpeed = (SPEED / 100.0) * 15.5
print(f'Speed: {seqSpeed}')
And if you need to use .format():
print('Speed: {0}'.format(seqSpeed))
And also there is:
print('Speed: %s' % x)

Python setting Decimal Place range without rounding?

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?
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]
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.
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.
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')
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)
also this:
>>> f = 1.678
>>> n = 2
>>> int(f * 10 ** n) / 10 ** n
1.67
Easiest way to get integer:
series_col.round(2).apply(lambda x: float(str(x).split(".",1)[0]))

Python Percentage Rounding [duplicate]

This question already has answers here:
How to make rounded percentages add up to 100%
(23 answers)
Closed 8 years ago.
I know how to round a number in Python, this is not a simple technical issue.
My issue is that rounding will make a set of percentages not adding up to 100%, when, technically, they should.
For example:
a = 1
b = 14
I want to compute the percentage of a in (a + b) and b in (a + b).
The answer should be
a/(a + b) = 1/15
b/(a + b) = 14/15
When I try to round those numbers, I got
1/15 = 6.66
14/15 = 93.33
(I was doing the flooring), which makes those two number doesn't add up to 100%.
In this case, we should do ceiling for 1/15, which is 6.67, and flooring for 14/15, which is 93.33. And now they add up to 100%. The rule in this case should be "rounding to the nearest number"
However, if we have a more complicate case, say 3 numbers:
a = 1
b = 7
c = 7
flooring:
1/15 = 6.66
7/15 = 46.66
7/15 = 46.66
Doesn't add up to 100%.
ceiling:
1/15 = 6.67
7/15 = 46.67
7/15 = 46.67
doesn't add up to 100%.
Rounding (to nearest number) is same as ceiling. Still doesn't add up to 100%.
So my question is what should I do to make sure they all add up to 100% in any cases.
Thanks in advance.
UPDATE:
Thanks for the tips from comments. I have took the "Largest Remainder" solution from the duplicate Post answer.
The code are:
def round_to_100_percent(number_set, digit_after_decimal=2):
"""
This function take a list of number and return a list of percentage, which represents the portion of each number in sum of all numbers
Moreover, those percentages are adding up to 100%!!!
Notice: the algorithm we are using here is 'Largest Remainder'
The down-side is that the results won't be accurate, but they are never accurate anyway:)
"""
unround_numbers = [x / float(sum(number_set)) * 100 * 10 ** digit_after_decimal for x in number_set]
decimal_part_with_index = sorted([(index, unround_numbers[index] % 1) for index in range(len(unround_numbers))], key=lambda y: y[1], reverse=True)
remainder = 100 * 10 ** digit_after_decimal - sum([int(x) for x in unround_numbers])
index = 0
while remainder > 0:
unround_numbers[decimal_part_with_index[index][0]] += 1
remainder -= 1
index = (index + 1) % len(number_set)
return [int(x) / float(10 ** digit_after_decimal) for x in unround_numbers]
Tested, seems work fine.
As others have commented, if your numbers are nice and round as in your example, you can use the fractions module to retain the accuracy of the rational numbers:
In [2]: from fractions import Fraction
In [5]: a = Fraction(1)
In [6]: b = Fraction(14)
In [7]: a/(a+b)
Out[7]: Fraction(1, 15)
In [8]: a/(a+b) + (b/(a+b))
Out[8]: Fraction(1, 1)
This obviously doesn't look good if you have really odd fractions.
Welcome to IEEE Floats.
The floating point numbers returned from math operations in python are approximates. On some values, the sum of percentages will be greater than 100.
You have two solutions: use the fraction or decimal modules OR, simply not want them to add up to 100%.

Wanting to convert cm^3 to L in python

I want to write a function that when I input the dimensions of a truncated cone (a cup) and an amount of liquid in litres returns how many of these cups can be filled up with the amount of liquid.I understand that 1L = 1000 cm^3 but I do not understand how I would incorporate it into my code to return the outcome I expect
def number_of_cups(bottom_radius, top_radius, height, litres_of_liquid):
volume = math.pi / 3 * height * (bottom_radius**2 + top_radius * bottom_radius + top_radius**2)
return int(filled_cup)
This is as far as I have got, I know I am close but I don't understand how to word my conversion,
That depends on the unit in which bottom_radius, top_radius and height are given. If we assume that those length are given in cm then
def number_of_cups(bottom_radius, top_radius, height, litres_of_liquid):
volume = math.pi / 3 * height * (bottom_radius**2 + top_radius * bottom_radius + top_radius**2)
return int( litres_of_liquid * 1000 / volume )
litres_of_liquid * 1000 is litres converted to cm^3. The int() could be replaced by math.floor() in case the number of completely full cups is intended, math.ceil() will give the number of full or partially filled cups.
Finally, there is a nice package magnitude which encapsulates a physical quantity. You could use this package in case the user wants to specify different length units.
The Formula stated by the OP is correct.
OK, just want to point out, your volume calculation seems wrong.
def number_of_cups(bottom_radius, top_radius, height, litres_of_liquid):
volume = 4 * math.pi * height * (bottom_radius**2 + top_radius**2)/2
filled_cup = 1000 * litres_of_liquid / volume
return int(filled_cup)
And in case you did't know, division is different in Python2 and Python3.
Python 2
>>> 1/2
0
Python 3
>>> 1/2
0.5
>>> 1//2
0
Throwing my own anwer to the pile:
#!/usr/bin/python2
import math
# nothing about units here , but let's say it's cm
def cup_vol(b_rad=3, t_rad=4, h=5):
vol = math.pi/3 * (b_rad**2 + t_rad + b_rad + t_rad**2) * h
return vol
def n_cups(liquid_amount, whole_cups=True): # nothing about units here
# liquid amount is Liter then first convert it to CM^3
liquid_amount = liquid_amount*1000
# this yields an int
if whole_cups:
return int(liquid_amount/cup_vol())
# else, return a real number with fraction
return liquid_amount/cup_vol()
if __name__ == '__main__':
print "4L fill %f cups" % n_cups(4)
print "4L fill %f cups (real)" % n_cups(4, whole_cups=False)
Running the above script yields:
4L fill 23.000000 cups
4L fill 23.873241 cups (real)

Categories