Precise math.log(x, 2) in Python - python

In python, I need to get the rounded down logarithm of positive integers for base 2, including big numbers.
However, since floating point math is used, I might get bad results, for example:
>>> import math
>>> int(math.log(281474976710655, 2))
48
However:
>>> 2 ** 48
281474976710656
So the correct result, rounded down, should be 47.
How can I get the correct value?

In Python 3, integers have a .bit_length method, so you should use that to get your rounded down base 2 logarithm.
Here's a short demo:
m = 2 ** 1000
for n in (281474976710655, m-1, m, m+1):
a = n.bit_length() - 1
b = 2 ** a
print(a, b <= n < 2 * b)
output
47 True
999 True
1000 True
1000 True

In python 3 ints even have an efficient .bit_length() method!
>>> (281474976710655).bit_length()
48
>>> (281474976710656).bit_length()
49
In python 2, instead of using floating point math, count the number of bits:
def log2(n):
assert n >= 1
return len(bin(n)) - 3 # bin() returns a string starting with '0b'
(Edited following this comment)

Related

Order of Operations - Python 3

Can someone explain why c is equal to 25 and not 30? I keep getting 30 by multiplying a*(b//a) and then adding b to it after.
a=10
b=3*(a-5)
c=b+(b//a)*a
Just do it step by step and you'll see that you're doing
c = 15 + 1*10
Hence c is 25. b//a is floor division, meaning 15/10 becomes 1
An easy way to understand whats going on is to print each steps:
a=10
b=3*(a-5)
print(b)
print(b//a)
print((b//a)*a)
print(b+(b//a)*a)
c=b+(b//a)*a
output
15
1
10
25
(15//10) is equal to 1 so the formula for c is equivalent to 15+1*10 The // operator is floor division which round down to the nearest integer. In additon all the values you are using are integers. To get 30 you need to use the normal divsion operator / and case one of the operands in the division to a floating point number, like this: c = b+(float(b)/a)*a That code sets c to 30.0.
c = b + (b//a)*a = b + ((b//a)*a) = 15 + ((15//10)*10) = 15 + (1*10) = 25
Does this clear it up?
The crucial part is 15//10, because // performs integer division which rounds down to the next integer. Note the difference between / and // in Python 3.
>>> 15/10
1.5
>>> 15//10
1

Python Partial Harmonics

Could someone help check why the result is always one and let me know what I did wrong? Thanks
Correct result should be: 1/1 + 1/2 + 1/3 == 1.83333333333.
x = int(input("Enter n: "))
assert x > 0, "n must be greater than zero!"
def one_over_n(x):
result = 0
for n in range(x):
n += 1
result += 1 / n
return result
r = one_over_n(x)
print("one_over_n( {0:d} ): {1:f}" .format(x, r))
It will work correctly on python 3, but not in python 2
>>> 1/2
0
That means you are just adding zeroes, to one. You will need to change either numerator or denominator to a float number e.g. 1/2.0, so change your code to
result += 1.0 / n
See Pep 238 to see why it was changed in python 3.
btw floating point numbers can't represent all fractions, so if you are just adding fractions, you can use Fraction class e.g.
>>> from fractions import Fraction as F
>>> F(1,1) + F(1,2) + F(1,3)
Fraction(11, 6)
As an alternative, to force Python 2 perform division as you expect (rather than integer division), add:
from __future__ import division

In Python, what is a good way to round towards zero in integer division?

1/2
gives
0
as it should. However,
-1/2
gives
-1
, but I want it to round towards 0 (i.e. I want -1/2 to be 0), regardless of whether it's positive or negative. What is the best way to do that?
Do floating point division then convert to an int. No extra modules needed.
Python 3:
>>> int(-1 / 2)
0
>>> int(-3 / 2)
-1
>>> int(1 / 2)
0
>>> int(3 / 2)
1
Python 2:
>>> int(float(-1) / 2)
0
>>> int(float(-3) / 2)
-1
>>> int(float(1) / 2)
0
>>> int(float(3) / 2)
1
Python's default division of integers is return the floor (towards negative infinity) with no ability to change that. You can read the BDFL's reason why.
To do 'round up' division, you would use:
>>> a=1
>>> b=2
>>> (a+(-a%b))//b
1
>>> a,b=-1,2
>>> (a+(-a%b))//b
0
To do truncation towards zero, and maintain integer division, you use (a+(-a%b))//b if either a or b are negative and the default division if both are positive.
This will do integer division and always round towards zero:
>>> a=1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a=-1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a,b=-3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
-1
>>> a,b=3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
1
footnote
Interestingly enough, C99 declares that round towards zero is the default:
#include <stdio.h>
int main(int argc, const char * argv[])
{
int a=-3;
int b=2;
printf("a=%d, b=%d, a/b=%d\n",a,b,a/b);
a=3;
printf("a=%d, b=%d, a/b=%d\n",a,b,a/b);
return 0;
}
Prints:
a=-3, b=2, a/b=-1
a=3, b=2, a/b=1
For what it's worth, my own favourite solution is this one. Integer arithmetic only, a single division, and everything else linear time:
def integer_divide_towards_zero(a, b):
return -(-a // b) if a < 0 else a // b
That assumes that b is positive, but in most of the applications I've seen that's true. If you need to deal with negative b too, then the function becomes marginally more complicated:
def integer_divide_towards_zero(a, b):
return -(-a // b) if (a < 0) ^ (b < 0) else a // b
Some sample outputs:
>>> integer_divide_towards_zero(11, 3)
3
>>> integer_divide_towards_zero(-11, 3)
-3
>>> integer_divide_towards_zero(6, 3)
2
>>> integer_divide_towards_zero(-6, 3)
-2
>>> integer_divide_towards_zero(11, -3)
-3
>>> integer_divide_towards_zero(-11, -3)
3
why reinvent the wheel, when there's a perfectly good math.trunc() function?
import math
print(math.trunc(-3.5))
>>-3
print(math.trunc(3.5))
>>3
Try this. Only works for numbers greater than -1
import math
x = .5
y = -.5
print math.floor(math.fabs(x))
>> 0
print math.floor(math.fabs(y))
>> 0
Correct code to do this is, in my opinion, too obscure to write as a 1-liner. So I'd put it in a function, like:
def int0div(a, b):
q = a // b
if q < 0 and b*q != a:
q += 1
return q
Good features: it works for any size of int, doesn't make any adjustment to the raw (a//b) result unless necessary, only does one division (% also does a division under the covers), and doesn't create any integers larger than the inputs. Those may or may not matter in your application; they become more important (for speed) if you use "big" integers.
Throwing my hat in with a few alternate ideas:
Multiple the sign of the number [abs(x)/x] by the abs(x)/2
(abs(x)/x)*(abs(x)/2)
Perform the addition, but if the number is less than zero add one to shift it closer to 0.
x/2 + int(x<0)
You can also use the Decimal module as part of the standard python libraries.
Specifically,
" The integer division operator // behaves analogously, returning the integer part of the true quotient (truncating towards zero) rather than its floor, so as to preserve the usual identity x == (x // y) * y + x % y:"
>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')
Also, have a look at Rounding Modes as they've got quite a few ways to view/round your information - Ceiling, down, floor, half-down, half-even, half-up, up and 05up rounding.
Decimal was written as a solution to the traditional problem of binary mathematics in a world expecting decimals solutions

Exercise on Summing Digits | What's with n // = 10 [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the reason for having ‘//’ in Python?
While trying to do an exercise on summing digits, I stumbled on this solution:
def sum_digits(n):
import math
total = 0
for i in range(int(math.log10(n)) + 1):
total += n % 10
n //= 10
return total
My question is, what does the second to last line do? How is that proper syntax?
That implements what is called floor division. Floor division (indicated by // here) truncates the decimal and returns the integer result, while 'normal' division returns the answer you may 'expect' (with decimals). In Python 3.x, a greater distinction was made between the two, meaning that the two operators return different results. Here is an example using Python 3:
>>> 10 / 3
3.3333333333333335
>>> 10 // 3
3
Prior to Python 3.x, there is no difference between the two, unless you use the special built-in from __future__ import division, which then makes the division operators perform as they would in Python 3.x (this is using Python 2.6.5):
In [1]: 10 / 3
Out[1]: 3
In [2]: 10 // 3
Out[2]: 3
In [3]: from __future__ import division
In [4]: 10 / 3
Out[4]: 3.3333333333333335
In [5]: 10 // 3
Out[5]: 3
Therefore when you see something like n //= 10, it is using the same +=/-=/*=/etc syntax that you may have seen, where it takes the current value of n and performs the operation before the equal sign with the following variable as the second argument, returning the result into n. For example:
In [6]: n = 50
In [7]: n += 10
In [8]: n
Out[8]: 60
In [9]: n -= 20
In [10]: n
Out[10]: 40
In [11]: n //= 10
In [12]: n
Out[12]: 4
// is the floor division operator. It always truncates the return value to the largest integer smaller than or equal to the answer.
The second to last line is a combination of operators, in a way, including an uncommon one, which is why it's a little confusing.
Let's piece it apart.
First, // in Python is floor division, which basically is division rounded down to the nearest whole number. Thus,
>>> 16//5
3
>>> 2//1
2
>>> 4//3
1
>>> 2//5
0
Finally, the = is there because of a Python syntax that allows one to perform an operation on a variable, and then immediately reassign the result to the variable. You've probably seen it most commonly in +=, as:
>>> a = 5
>>> a += 7
>>> a
12
In this case, //= means "perform floor division, floor dividing the variable by the second argument, then assign the result to the original input variable." Thus:
>>> a = 10
>>> a //= 6
>>> a
1
for the assignment in Python A += B equals to A = A + B ,A *= B equals to A = A * B
same thing applies to "Floor Divide" as well , A //= B equals to A = A // B
Floor Division means return the truncated integer number
>>> 5 // 3 # 1.6
1 # 0.6 will be throw off

How to set minimum value to a division operation in python?

Is there a standard library function which will set a minimum value to a division operation, for example:
min(1, a/b)
This will ensure that min value of operation above will always be 1, never 0.
Such as:
min(1, 1/5)
1
Also, how do I round up a division:
round_up(1/5) = 1
I always get "0" when I divide 1/5, even with ceil function:
math.ceil(1/5)
0
If you want to use floating point division as default, you can do from __future__ import division:
>>> 1/5
0
>>> from __future__ import division
>>> 1/5
0.2
>>> math.ceil(1/5)
1.0
If you need the result to be of integer type, e.g. for indexing, you can use
int(math.ceil(1/5))
The result of 1/5 is an integer already. If you want the floating point version you need to do 1.0/5. The math.ceil function will then work as you expect: math.ceil(1.0/5) = 1.0.
If you're working with variables instead of constants, use the float(x) function to convert an integer into a floating point.
In [4]: 1/5
Out[4]: 0
In [5]: math.ceil(1/5)
Out[5]: 0.0
In [7]: float(1)/5
Out[7]: 0.2
In [8]: math.ceil(float(1)/5)
Out[8]: 1.0
You could make a round up function for integers like this
>>> def round_up(p, q):
... d, r = divmod(p, q)
... if r != 0:
... d += 1
... return d
...
>>> round_up(1, 5)
1
>>> round_up(0, 5)
0
>>> round_up(5, 5)
1
>>> round_up(6, 5)
2
>>>
Your example doesn't work because an integer dividing an integer is an integer.
As for your min question - what you wrote is probably the best you can do.
I don't know about anything in the standard library, but if you are just trying to make sure the answer is never less than 1, the function is pretty easy:
def min_dev(x,y):
ans = x/y
if ans < 1: # ensures answer cannot be 0
return 1
else: # answers greater than 1 are returned normally
return ans
If, instead, you are looking to round up every answer:
def round_up(x,y):
ans = x//y # // is the floor division operator
if x % y == 1: # tests for remainder (returns 0 for no, 1 for yes)
ans += 1 # same as ans = ans + 1
return ans
else:
return ans
This will round up any answer with a remainder.
I believe Python 3.3 (and I know 3.4) return a float by default for integer division: https://docs.python.org/3/tutorial/introduction.html

Categories

Resources