Python 3.x rounding half up - python

I know that questions about rounding in python have been asked multiple times already, but the answers did not help me. I'm looking for a method that is rounding a float number half up and returns a float number. The method should also accept a parameter that defines the decimal place to round to. I wrote a method that implements this kind of rounding. However, I think it does not look elegant at all.
def round_half_up(number, dec_places):
s = str(number)
d = decimal.Decimal(s).quantize(
decimal.Decimal(10) ** -dec_places,
rounding=decimal.ROUND_HALF_UP)
return float(d)
I don't like it, that I have to convert float to a string (to avoid floating point inaccuracy) and then work with the decimal module.
Do you have any better solutions?
Edit: As pointed out in the answers below, the solution to my problem is not that obvious as correct rounding requires correct representation of numbers in the first place and this is not the case with float. So I would expect that the following code
def round_half_up(number, dec_places):
d = decimal.Decimal(number).quantize(
decimal.Decimal(10) ** -dec_places,
rounding=decimal.ROUND_HALF_UP)
return float(d)
(that differs from the code above just by the fact that the float number is directly converted into a decimal number and not to a string first) to return 2.18 when used like this: round_half_up(2.175, 2) But it doesn't because Decimal(2.175) will return Decimal('2.17499999999999982236431605997495353221893310546875'), the way the float number is represented by the computer.
Suprisingly, the first code returns 2.18 because the float number is converted to string first. It seems that the str() function conducts an implicit rounding to the number that was initially meant to be rounded. So there are two roundings taking place. Even though this is the result that I would expect, it is technically wrong.

Rounding is surprisingly hard to do right, because you have to handle floating-point calculations very carefully. If you are looking for an elegant solution (short, easy to understand), what you have like like a good starting point. To be correct, you should replace decimal.Decimal(str(number)) with creating the decimal from the number itself, which will give you a decimal version of its exact representation:
d = Decimal(number).quantize(...)...
Decimal(str(number)) effectively rounds twice, as formatting the float into the string representation performs its own rounding. This is because str(float value) won't try to print the full decimal representation of the float, it will only print enough digits to ensure that you get the same float back if you pass those exact digits to the float constructor.
If you want to retain correct rounding, but avoid depending on the big and complex decimal module, you can certainly do it, but you'll still need some way to implement the exact arithmetics needed for correct rounding. For example, you can use fractions:
import fractions, math
def round_half_up(number, dec_places=0):
sign = math.copysign(1, number)
number_exact = abs(fractions.Fraction(number))
shifted = number_exact * 10**dec_places
shifted_trunc = int(shifted)
if shifted - shifted_trunc >= fractions.Fraction(1, 2):
result = (shifted_trunc + 1) / 10**dec_places
else:
result = shifted_trunc / 10**dec_places
return sign * float(result)
assert round_half_up(1.49) == 1
assert round_half_up(1.5) == 2
assert round_half_up(1.51) == 2
assert round_half_up(2.49) == 2
assert round_half_up(2.5) == 3
assert round_half_up(2.51) == 3
Note that the only tricky part in the above code is the precise conversion of a floating-point to a fraction, and that can be off-loaded to the as_integer_ratio() float method, which is what both decimals and fractions do internally. So if you really want to remove the dependency on fractions, you can reduce the fractional arithmetic to pure integer arithmetic; you stay within the same line count at the expense of some legibility:
def round_half_up(number, dec_places=0):
sign = math.copysign(1, number)
exact = abs(number).as_integer_ratio()
shifted = (exact[0] * 10**dec_places), exact[1]
shifted_trunc = shifted[0] // shifted[1]
difference = (shifted[0] - shifted_trunc * shifted[1]), shifted[1]
if difference[0] * 2 >= difference[1]: # difference >= 1/2
shifted_trunc += 1
return sign * (shifted_trunc / 10**dec_places)
Note that testing these functions brings to spotlight the approximations performed when creating floating-point numbers. For example, print(round_half_up(2.175, 2)) prints 2.17 because the decimal number 2.175 cannot be represented exactly in binary, so it is replaced by an approximation that happens to be slightly smaller than the 2.175 decimal. The function receives that value, finds it smaller than the actual fraction corresponding to the 2.175 decimal, and decides to round it down. This is not a quirk of the implementation; the behavior derives from properties of floating-point numbers and is also present in the round built-in of Python 3 and 2.

I don't like it, that I have to convert float to a string (to avoid
floating point inaccuracy) and then work with the decimal module. Do
you have any better solutions?
Yes; use Decimal to represent your numbers throughout your whole program, if you need to represent numbers such as 2.675 exactly and have them round to 2.68 instead of 2.67.
There is no other way. The floating point number which is shown on your screen as 2.675 is not the real number 2.675; in fact, it is very slightly less than 2.675, which is why it gets rounded down to 2.67:
>>> 2.675 - 2
0.6749999999999998
It only shows in string form as '2.675' because that happens to be the shortest string such that float(s) == 2.6749999999999998. Note that this longer representation (with lots of 9s) isn't exact either.
However you write your rounding function, it is not possible for my_round(2.675, 2) to round up to 2.68 and also for my_round(2 + 0.6749999999999998, 2) to round down to 2.67; because the inputs are actually the same floating point number.
So if your number 2.675 ever gets converted to a float and back again, you have already lost the information about whether it should round up or down. The solution is not to make it float in the first place.

After trying for a very long time to produce an elegant one-line function, I ended up getting something that is comparable to a dictionary in size.
I would say the simplest way to do this is just to
def round_half_up(inp,dec_places):
return round(inp+0.0000001,dec_places)
i would acknowledge that this is not accurate in every cases, but should work if you just want a simple quick workaround.

Related

How can I check the length of a long float? Python is truncating the length [duplicate]

I have some number 0.0000002345E^-60. I want to print the floating point value as it is.
What is the way to do it?
print %f truncates it to 6 digits. Also %n.nf gives fixed numbers. What is the way to print without truncation.
Like this?
>>> print('{:.100f}'.format(0.0000002345E-60))
0.0000000000000000000000000000000000000000000000000000000000000000002344999999999999860343602938602754
As you might notice from the output, it’s not really that clear how you want to do it. Due to the float representation you lose precision and can’t really represent the number precisely. As such it’s not really clear where you want the number to stop displaying.
Also note that the exponential representation is often used to more explicitly show the number of significant digits the number has.
You could also use decimal to not lose the precision due to binary float truncation:
>>> from decimal import Decimal
>>> d = Decimal('0.0000002345E-60')
>>> p = abs(d.as_tuple().exponent)
>>> print(('{:.%df}' % p).format(d))
0.0000000000000000000000000000000000000000000000000000000000000000002345
You can use decimal.Decimal:
>>> from decimal import Decimal
>>> str(Decimal(0.0000002345e-60))
'2.344999999999999860343602938602754401109865640550232148836753621775217856801120686600683401464097113374472942165409862789978024748827516129306833728589548440037314681709534891496105046826414763927459716796875E-67'
This is the actual value of float created by literal 0.0000002345e-60. Its value is a number representable as python float which is closest to actual 0.0000002345 * 10**-60.
float should be generally used for approximate calculations. If you want accurate results you should use something else, like mentioned Decimal.
If I understand, you want to print a float?
The problem is, you cannot print a float.
You can only print a string representation of a float. So, in short, you cannot print a float, that is your answer.
If you accept that you need to print a string representation of a float, and your question is how specify your preferred format for the string representations of your floats, then judging by the comments you have been very unclear in your question.
If you would like to print the string representations of your floats in exponent notation, then the format specification language allows this:
{:g} or {:G}, depending whether or not you want the E in the output to be capitalized). This gets around the default precision for e and E types, which leads to unwanted trailing 0s in the part before the exponent symbol.
Assuming your value is my_float, "{:G}".format(my_float) would print the output the way that the Python interpreter prints it. You could probably just print the number without any formatting and get the same exact result.
If your goal is to print the string representation of the float with its current precision, in non-exponentiated form, User poke describes a good way to do this by casting the float to a Decimal object.
If, for some reason, you do not want to do this, you can do something like is mentioned in this answer. However, you should set 'max_digits' to sys.float_info.max_10_exp, instead of 14 used in the answer. This requires you to import sys at some point prior in the code.
A full example of this would be:
import math
import sys
def precision_and_scale(x):
max_digits = sys.float_info.max_10_exp
int_part = int(abs(x))
magnitude = 1 if int_part == 0 else int(math.log10(int_part)) + 1
if magnitude >= max_digits:
return (magnitude, 0)
frac_part = abs(x) - int_part
multiplier = 10 ** (max_digits - magnitude)
frac_digits = multiplier + int(multiplier * frac_part + 0.5)
while frac_digits % 10 == 0:
frac_digits /= 10
scale = int(math.log10(frac_digits))
return (magnitude + scale, scale)
f = 0.0000002345E^-60
p, s = precision_and_scale(f)
print "{:.{p}f}".format(f, p=p)
But I think the method involving casting to Decimal is probably better, overall.

sometimes missing a cent when translating euros to euro cents

I have to translate euro's (in a string) to euro cents (int):
Examples:
'12,1' => 1210
'14,51' => 1451
I use this python function:
int(round(float(amount.replace(',', '.')), 2) * 100)
But with this amount '1229,84' the result is : 122983
Update
I use the solution from Wim, bacause I use integers in both Python / Jinja and javascript for currency artitmetic. See also the answer from Chepner.
int(round(100 * float(amout.replace(',', '.')), 2))
My questions was anwered by Mr. Me, who explained the above result.
What the Docs Say, and a simple explanation
I tried it out, and was surprised that this was happening. So I turned to the documentation, and there is a little note in there that says.
Note The behavior of round() for floats can be surprising: for
example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This
is not a bug: it’s a result of the fact that most decimal fractions
can’t be represented exactly as a float.
Now what does that mean, most decimal fractions can't be represented as a float. Well the documentations follows up with a great link at explains this, but since you probably didn't come here to read a nerdy technical document, let me summarize what is going on.
Python uses the IEEE-754 floating point standard to represent floats. This standard compromises accuracy for speed. Some numbers cannot be accurately represented. For example .1 is actually represented as 0.1000000000000000055511151231257827021181583404541015625. Interestingly, .1 in binary is actually an infinitely repeating number, just like 1/3 is an infinitely repeating .333333.
An Under the Hood Case Study
Now on to your particular case. This was pretty fun to look into, and this is what I discovered.
first lets simplify what you where trying to do
>>> amount = '1229,84'
>>> int(round(float(amount.replace(',', '.')), 2) * 100)
>>> 122983
to
>>>int(1229.84 * 100)
>>> 122983
Sometimes Python1 is unable to 100% accurately display binary floating point numbers, for the same reason we are unable to display the fraction 1/3 as a decimal. When this happens Python hides any extra digits. .1 is actually stored as -0.100000000000000092, but Python will display it as .1 if you type it into the console. We can see those extra digits by doing int(1.1) - 1.13. we can apply this int(myNum) - myNum formula to most floating point numbers to see the extra hidden digits behind them.4. In your case we would do the following.
>>> int(1229.84) - 1229.84
-0.8399999999999181
1229.84 is actually 1229.8399999999999181. Continuing on.5
>>> 1229.84, 2) * 100
122983.99999999999 #there's all of our hidden digits showing up.
Now on to the last step. This is the part we are concerned about. Changing it back to an integer.
>>> int(122983.99999999999)
122983
It rounds downwards instead of upwards, however, if we never had multiplied it by 100, we would still have 2 more 9s at the end, and Python would round up.
>>> int(122983.9999999999999)
122984
??? Now what is going on. Why is Python rounding 122983.99999999999 down, but it rounds 122983.9999999999999 up? Well whenever Python turns a float into a integer it rounds down. However, you have to remember that to Python 122983.9999999999999 with the extra two 99s at the end is the same thing as 122984.0 For example.
>>> 122983.9999999999999
122984.0
>>> a = 122983.9999999999999
>>> int(a) - a
0.0
and without the two extra 99s on the end.
>>> 122983.99999999999
122983.99999999999
>>> a=122983.99999999999
>>> int(a) - a
-0.9999999999854481
Python is definitely treating 122983.9999999999999 as 122984.0 but not 122983.99999999999. Now back to casting 122983.99999999999 to an integer. Because we have created ourselves a decimal portion that is less than 122984 that Python sees as being a seperate number from 122984, and because casting to an integer always causes Python to round down, we get 122983 as a result.
Whew. That was a lot to go through, but I sure learned a lot writing this out, and I hope you did to. The solution to all of this is to use decimal numbers instead of floats which compromises speed for accuracy.
What about rounding? The original problem had some rounding in it as well -- it's useless. See appendix item 6.
The Solution
a) The easiest solution is to use the decimal module instead of floating point numbers. This is the preferred way of doing things in any finance or accounting program.
The documentation also mentioned the following solutions which I've summarized.
b) The exact value can be expressed and retrieved in a hexadecimal form via myFloat.hex() and float.fromhex(myHex)
c) The exact value can also be retrieved as a fraction through myFloat.as_integer_ratio()
d) The documentation briefly mentions using SciPy for floating point arithmitic, however this SO question mentions that SciPy's NumPy floats are nothing more than aliases to the built-in float type. The decimal module would be a better solution.
Appendix
1 - Even though I will often refer to Python's behavior, the things I talk about are part of the IEEE-754 floating point standard which is what the major programming languages use for their floating point numbers.
2 - int(1.1) - 1.1 gives me -0.10000000000000009, but according to the documentation .1 is really 0.1000000000000000055511151231257827021181583404541015625
3 - We used int(1.1) - 1.1 instead of int(.1) - .1 because int(.1) - .1 does not give us the hidden digits, but according to the documentation they should still be there for .1, hence I say int(someNum) -someNum works most of the time, but not all of the time.
4 - When we use the formula int(myNum) - myNum what is happening is that casting the number to an integer will round the number down so int(3.9) becomes 3, and when we minus 3 from 3.9 we are left with -.9. However, for some reason that I do not know, when we get rid of all the whole numbers, and we're just left with the decimal portion, Python decides to show us everything -- the whole mantissa.
5 - this does not really affect the outcome of our analysis, but when multiplying by 100, instead of the hidden digits being shifted over by 2 decimal places, they changed a little as well.
>>> a = 1229.84
>>> int(a) - a
-0.8399999999999181
>>> a = round(1229.84, 2) * 100
>>> int(a) - a
-0.9999999999854481 #I expected -0.9999999999918100?
6 - It may seem like we can get rid of all those extra digits by rounding to two decimal places.
>>> round(1229.84, 2) # which is really round(1229.8399999999999181, 2)
1229.84
But when we use our int(someNum) - someNum formula to see the hidden digits, they are still there.
>>> a = round(1229.84, 2)
>>> int(a) - a
-0.8399999999999181
This is because Python cannot store 1229.84 as a binary floating point number. It can't be done. So... rounding 1229.84 does absolutely nothing.
Don't use floating-point arithmetic for currency; rounding error for values that cannot be represented exactly will cause the type of loss you are seeing. Instead, convert the string representation to an integer number of cents, which you can convert to euros-and-cents for display as needed.
euros, cents = '12,1'.split(',') # '12,1' -> ('12', '1')
cents = 100*int(euros) + int(cents * 10 if len(cents) == 1 else 1) # ('12', '1') -> 1210
(Notice you'll need a check to handle cents without a trailing 0.)
display_str = '%d,%d' % divMod(cents, 100) # 1210 -> (12, 10) -> '12.10'
You can also use the Decimal class from the decimal module, which essentially encapsulates all the logic for using integers to represent fractional values.
As #wim mentions in a comment, use the Decimal type from the stdlib decimal module instead of the built in float type. Decimal objects do not have the binary rounding behavior that floats have and also have a precision that can be user defined.
Decimal should be used anywhere you are doing financial calculations or anywhere you need floating point calculations that behave like the decimal math people learn in school (as opposed to the binary floating point behavior of the built in float type).

How to check if a float value is within a certain range and has a given number of decimal digits?

How to check if a float value is within a range (0.50,150.00) and has 2 decimal digits?
For example, 15.22366 should be false (too many decimal digits). But 15.22 should be true.
I tried something like:
data= input()
if data in range(0.50,150.00):
return True
Is that you are looking for?
def check(value):
if 0.50 <= value <= 150 and round(value,2)==value:
return True
return False
Given your comment:
i input 15.22366 it is going to return true; that is why i specified the range; it should accept 15.22
Simply said, floating point values are imprecise. Many values don't have a precise representation. Say for example 1.40. It might be displayed "as it":
>>> f = 1.40
>>> print f
1.4
But this is an illusion. Python has rounded that value in order to nicely display it. The real value as referenced by the variable f is quite different:
>>> from decimal import Decimal
>>> Decimal(f)
Decimal('1.399999999999999911182158029987476766109466552734375')
According to your rule of having only 2 decimals, should f reference a valid value or not?
The easiest way to fix that issue is probably to use round(...,2) as I suggested in the code above. But this in only an heuristic -- only able to reject "largely wrong" values. See my point here:
>>> for v in [ 1.40,
... 1.405,
... 1.399999999999999911182158029987476766109466552734375,
... 1.39999999999999991118,
... 1.3999999999999991118]:
... print check(v), v
...
True 1.4
False 1.405
True 1.4
True 1.4
False 1.4
Notice how the last few results might seems surprising at first. I hope my above explanations put some light on this.
As a final advice, for your needs as I guess them from your question, you should definitively consider using "decimal arithmetic". Python provides the decimal module for that purpose.
float is the wrong data type to use for your case, Use Decimal instead.
Check python docs for issues and limitations. To quote from there (I've generalised the text in Italics)
Floating-point numbers are represented in computer hardware as base 2 (binary) fractions.
no matter how many base 2 digits you’re willing to use, some decimal value (like 0.1) cannot be represented exactly as a base 2 fraction.
Stop at any finite number of bits, and you get an approximation
On a typical machine running Python, there are 53 bits of precision available for a Python float, so the value stored internally when you enter a decimal number is the binary fraction which is close to, but not exactly equal to it.
The documentation for the built-in round() function says that it rounds to the nearest value, rounding ties away from zero.
And finally, it recommends
If you’re in a situation where you care which way your decimal halfway-cases are rounded, you should consider using the decimal module.
And this will hold for your case as well, as you are looking for a precision of 2 digits after decimal points, which float just can't guarantee.
EDIT Note: The answer below corresponds to original question related to random float generation
Seeing that you need 2 digits of sure shot precision, I would suggest generating integer random numbers in range [50, 15000] and dividing them by 100 to convert them to float yourself.
import random
random.randint(50, 15000)/100.0
Why don't you just use round?
round(random.uniform(0.5, 150.0), 2)
Probably what you want to do is not to change the value itself. As said by Cyber in the comment, even if your round a floating point number, it will always store the same precision. If you need to change the way it is printed:
n = random.uniform(0.5, 150)
print '%.2f' % n # 58.03
The easiest way is to first convert the decimal to string and split with '.' and check if the length of the character. If it is >2 then pass on. i.e. Convert use input number to check if it is in a given range.
a=15.22366
if len(str(a).split('.')[1])>2:
if 0.50 <= value <= 150:
<do your stuff>>

Python: a could be rounded to b in the general case

As a part of some unit testing code that I'm writing, I wrote the following function. The purpose of which is to determine if 'a' could be rounded to 'b', regardless of how accurate 'a' or 'b' are.
def couldRoundTo(a,b):
"""Can you round a to some number of digits, such that it equals b?"""
roundEnd = len(str(b))
if a == b:
return True
for x in range(0,roundEnd):
if round(a,x) == b:
return True
return False
Here's some output from the function:
>>> couldRoundTo(3.934567892987, 3.9)
True
>>> couldRoundTo(3.934567892987, 3.3)
False
>>> couldRoundTo(3.934567892987, 3.93)
True
>>> couldRoundTo(3.934567892987, 3.94)
False
As far as I can tell, it works. However, I'm scared of relying on it considering I don't have a perfect grasp of issues concerning floating point accuracy. Could someone tell me if this is an appropriate way to implement this function? If not, how could I improve it?
Could someone tell me if this is an appropriate way to implement this function?
It depends. The given function will behave surprisingly if b isn't precisely equal to a value that would normally be obtained directly from decimal-to-binary-float conversion.
For example:
>>> print(0.1, 0.2/2, 0.3/3)
0.1 0.1 0.1
>>> couldRoundTo(0.123, 0.1)
True
>>> couldRoundTo(0.123, 0.2/2)
True
>>> couldRoundTo(0.123, 0.3/3)
False
This fails because the calculation of 0.3 / 3 results in a slightly different representation than 0.1 and 0.2 / 2 (and round(0.123, 1)).
If not, how could I improve it?
Rule of thumb: if your calculation specifically involves decimal digits in any way, just use Decimal, to avoid all the lossy base-2 round-tripping.
In particular, Decimal includes a helper called quantize that makes this problem trivially easy:
from decimal import Decimal
def roundable(a, b):
a = Decimal(str(a))
b = Decimal(str(b))
return a.quantize(b) == b
One way to do it:
def could_round_to(a, b):
(x, y) = map(len, str(b).split('.'))
round_format = "%" + "%d.%df"%(x, y)
return round_format%a == str(b)
First, we take the number of digits before and after the decimal in x and y. Then, we construct a format such as %x.yf. Then, we supply a to the format string.
>>> "%2.2f"%123.1234
'123.12'
>>> "%2.2f"%123.1264
'123.13'
>>> "%3.2f"%000.001
'0.00'
Now, all that's left is comparing the strings.
The only point that I'm afraid of is the conversion from strings to floating points when interpreting floating-point literals (as in http://docs.python.org/reference/lexical_analysis.html#floating-point-literals). I don't know if there is any guarantee that a floating-point literal will evaluate to the floating-point number that is closest to the given string. This mentioned section is the place in the specification where I would expect such a guarantee.
For example, Java is much more specific about what to expect from a string literal. From the documentation of Double.valueOf(String):
[...] [the argument] is regarded as representing an exact decimal value in the usual "computerized scientific notation" or as an exact hexadecimal value; this exact numerical value is then conceptually converted to an "infinitely precise" binary value that is then rounded to type double by the usual round-to-nearest rule of IEEE 754 floating-point arithmetic [...]
Unless you can find such a guarantee anywhere in the Python documentation, you can be just lucky, because some earlier floating-point libraries (on which Python might rely) convert a string just to a floating-point number nearby, not to the best available.
Unfortunately, it seems to me that neither round, nor float, nor the specification for floating-point literaly give you any usable guarantee.
If you purpose is to test if round function will round to the target, then you are correct. Otherwise (what else is the purpose?) if you are in doubt , you should use decimal module

Fractions with decimal precision

Is there a pure python implementation of fractions.Fraction that supports longs as numerator and denominator? Unfortunately, exponentiation appears to be coded in to return a float (ack!!!), which should at least support using decimal.Decimal.
If there isn't, I suppose I can probably make a copy of the library and try to replace occurrences of float() with something appropriate from Decimal but I'd rather something that's been tested by others before.
Here's a code example:
base = Fraction.from_decimal(Decimal(1).exp())
a = Fraction(69885L, 53L)
x = Fraction(9L, 10L)
print base**(-a*x), type(base**(-a*x))
results in 0.0 <type 'float'> where the answer should be a really small decimal.
Update: I've got the following work-around for now (assuming, for a**b, that both are fractions; of course, I'll need another function when exp_ is a float or is itself a Decimal):
def fracpow(base, exp_):
base = Decimal(base.numerator)/Decimal(base.denominator)
exp_ = Decimal(exp_.numerator)/Decimal(exp_.denominator)
return base**exp_
which gives the answer 4.08569925773896097019795484811E-516.
I'd still be interested if there's a better way of doing this without the extra functions (I'm guessing if I work with the Fraction class enough, I'll find other floats working their way into my results).
"Raise to a power" is not a closed operation over the rationals (differently from the usual four arithmetic operations): there is no rational number r such that r == 2 ** 0.5. Legend has it that Pythagoras (from whose theorem this fact so simply follows) had his disciple Hippasus killed for the horrible crime of proving this; looks like you sympathize wit Pythagoras' alleged reaction;-), given your weird use of "should".
Python's fractions are meant to be exact, so inevitably there are case in which raising a fraction to another fraction's power will be absolutely unable to return a fraction as its result; and "should" just cannot be sensibly applied to a mathematical impossibility.
So the best you can do is to approximate your desired result, e.g. by getting a result that's not an exact fraction (floats are generally considered sufficient for the purpose) and then further approximating it back with a fraction. Most existing pure-Python implementations (there are many rationals.py files found around the net;-) prefer not to implement a ** operator at all, but of course there's nothing stopping you from making a different design decision in your own implementation!-)
You can write your own "pow" function for fractions that doesn't use floating-point exponentiation. Is that what you're trying to do?
This will raise a fraction to an integer power with falling back to float.
def pow( fract, exp ):
if exp == 0:
return fract
elif exp % 2 == 0:
t = pow( fract, exp//2 )
return t*t
else:
return fract*pos( fract, exp-1 )

Categories

Resources