Converting from Float to Int changed the output - python

I defined a simple sqrt function to calculate a square root of a given number.
def sqrt(n):
low = 0
up = n
for i in range(50):
mid = float(low+up)/2
if pow(mid,2) < n:
low = mid
elif pow(mid,2) > n:
up = mid
else:
break
return mid
When I do:
print(sqrt(9))
I get 3.0 as the output. However when I do:
print(int(sqrt(9))) I get 2.
Could somebody please help me understand why this is happening?
Thank you.

Actually, sqrt(9) returns 2.9999999999999973 [1], at least in Python version 3.5 (and perhaps all versions 3.x?). And int returns only the integer component of the number. That's why you get 2 as the result, as the integer component of 2.9999999999999973 is indeed 2.
If you want to round the result to the nearest integer, you can do round(sqrt(9)) which produces 3.
[1] To understand why this happens and how to fix this issue, you can refer to this post.

It is because of rounding. Your method definition actually computes the sqrt(9) to be 2.9999999999999973. However the rounding is not applied to casting, therefore the decimal is lost in the casting of int(2.9999999999999973).
When you print directly, python applies rounding which brings this value up to 3.
Python 2.7 output:
Python 2.7.17 (v2.7.17:c2f86d86e6, Oct 19 2019, 21:01:17) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> def sqrt(n):
... low = 0
... up = n
... for i in range(50):
... mid = float(low+up)/2
... if pow(mid,2) < n:
... low = mid
... elif pow(mid,2) > n:
... up = mid
... else:
... break
... return mid
...
>>> sqrt(9)
2.9999999999999973
>>> print(sqrt(9))
3.0
>>> print(int(sqrt(9)))
2
>>>

If you want to get converted into int you can use the following:
print(int(round(sqrt(9))))

Related

Is there a way to know whether something was rounded up or down in python? [duplicate]

This question already has answers here:
Round to 5 (or other number) in Python
(21 answers)
Closed 2 years ago.
I basically want to know whether the result of my equation (which is a simple one like this x / y) was rounded up or down.
The reason is that I have two simple statements after the rounding line like this:
if h % 2 != 0: h = h + 1
if h % 4 != 0: h = h + 2
and based on the direction of the rounding I would choose the + or - operator, so if the result was rounded up and h % 2 != 0 then it would be h = h + 1 and if it was rounded down then h = h - 1.
Does round() give that kind of information?
Also, is my math correct? (I want the result to be dividable by 4)
Try this to round to 4 directly :
import math
h = 53.75
rounded = math.round(h / 4) * 4
if (rounded > h):
print("Rounded up by " + str(rounded - h))
else:
print("Rounded down by " + str(h - rounded))
Using round() if the number after the given decimal is:
>=5 that + 1 will be added to the final value.
<5 that the final value will return as is to the mentioned decimals.
But you can use ceil or floor from the math package where it always rounds up or down, respectively.
import math
>>> math.ceil(5.2)
6
>>> math.floor(5.9)
5
Let's say you want to know whether 3.9 and 4.4 were rounded. You can do something like this:
def is_rounded_down(val, ndigits=None):
return round(val, ndigits) < val
Then you can simply call the function to find out
>>> is_rounded_down(3.9)
False
>>> is_rounded_down(4.4)
True
By default round() doesn't give that information, so you need to check yourself.
For Python 2.X integer division returns an integer and always rounds down.
add#LM1756:~$ python
Python 2.7.13 (default, Sep 26 2018, 18:42:22)
>>> print 8/3
2
>>> print type(5/2)
<type 'int'>
For Python 3.X integer division returns a float, and so there is no rounding.
add#LM1756:~$ python3
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
>>> print(8/3)
2.6666666666666665
>>> type(8/3)
<class 'float'>
>>>

Use python to calculate a special limit

I want to calculate this expression:
(1 + 1 / math.inf) ** math.inf,
which should evaluates to e. However Python returns 1. Why is that?
=====UPDATE========
What I want to do here is to derive the effective annual rate from user's input, APR (annual percentage rate).
def get_EAR(APR, conversion_times_per_year = 1):
return (1 + APR / conversion_times) ** conversion_times - 1
I would want this expression to also apply to continuous compounding. Yes I understand I can write if statements to differentiate continuous compounding from normal cases (and then I can use the constant e directly), but I would better prefer an integrated way.
The calculation of limits is not implemented in python by default, for this you could use sympy
from sympy import *
x= symbols('x')
r = limit((1+1/x)**x, x, oo)
print(r)
Output:
E
Because you are esssentially performing two separate limits:
lim x->infty ((lim y->infty (1 + 1/y))^x)
which Python correctly evaluates as 1.
Here is a poor-man's-implementation of the proper limit:
def euler(x):
return (1+1/x)**x
for i in range(10):
print(euler(10**i))
2.0
2.5937424601000023
2.7048138294215285
2.7169239322355936
2.7181459268249255
2.7182682371922975
2.7182804690957534
2.7182816941320818
2.7182817983473577
2.7182820520115603
You could use the mpmath (http://mpmath.org/) package here:
>>> import mpmath as mp
>>> f = lambda x: (1.0 + 1.0/x)**x
>>> mp.limit(f, mp.inf)
mpf('2.7182818284590451')
I think there is no limit calculation here since there is no variable here that for which the whole statement can be calculated at different values of the variable.
Python simply does the calculation the simplest way possible. Pythons compiler simply turns the 1/math.inf to 0 and then evaluates 1 to the power of math.inf as 1.
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
import sys
import math
E = sys.float_info.epsilon
e = (1 + E) ** (1 / E)
print(e, math.e, e == math.e)
OUTPUT:
2.718281828459045 2.718281828459045 True

Bitwise 'AND' operator and its evaluation in a code

I've came across bitwise operators, and they really seem odd to me. Just wanted to get clarifications on two questions that I don't fully understand. The first piece of code is:
x = raw_input('Enter a digit: ')
print 'x is %s' % ('Even', 'Odd')[x & 1]
The question is the following - How does it exactly evaluates to 'Even' if I enter an even digit, and how does it pick the first element in parenthesis after evaluation?
On top of the that, can you please explain this piece of code:
if a[i-1] & 1 and a[i] & 1:
do some stuff
Thank you all
Bitwise operations work on binary representations of your integer numbers.
if a[i-1] & 1 and a[i] & 1:
do some stuff
Checks if both the entries at positions i and i-1 are odd numbers. This is realized by checking if the rightmost (least significant) bit of the numbers is 1. Take 42 and 23 as an example:
>>> bin(42)
'0b101010'
>>> bin(23)
'0b10111'
>>> bin(1)
'0b1'
Now you can apply a bitwise AND with one to both numbers. This operator returns a binary number which has a 1 on those positions, where the first AND the second input number have a 1-bit (and only there). Shorter numbers are padded with leading zeros:
binary decimal
101010 = 42
& 000001 = 1
--------
000000 = 0
10111 = 23
& 00001 = 1
--------
00001 = 1
So basically this is another way of doing:
if a[i-1]%2 == 1 and a[i]%2 == 1:
do some stuff
Your code is broken, since it applies &, the bitwise AND, to x which holds a string. Here's what I got when I tried your code in Python 2.x:
Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> x=raw_input("enter a digit")
enter a digit4
>>> x
'4'
>>> x&1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'str' and 'int'
You need to parse it as integer:
print "x is %s" % ("even", "odd")[int(x) & 1]
This works by "masking" out the right-most bit of x using & 1. This will be set if the number is odd, and clear if it's even. The resulting number (0 or 1) is used to index into the pair ("even", "odd").

Python: Median of a list of numbers

When I run my program on PyScripter, I get the expected median of 4.5. But running the same code on Ideone as here or on codeacademy returns 4. Any idea why the different results? Thanks.
#Create a function that returns the median of a list of numbers
def median(list_of_numbers):
#Make a copy of list_of_numbers and sort the new list
lst = list_of_numbers
lst = sorted(lst)
#Get the length of list and use it to index through the list
lst_length = len(lst)
index = int(lst_length/2)
#If length if even, average the two middle numbers
if lst_length%2==0:
a= lst[index-1]
b = lst[index]
result = (a+b)/2
#If length is odd, return the middle number
else:
result = lst[index]
return result
print (median([4, 5, 5, 4]))
My PyScripter version: * Python 3.3.5 (v3.3.5:62cf4e77f785, Mar 9 2014, 10:37:12) [MSC v.1600 32 bit (Intel)] on win32. *
For Python 2.x you will need to replace both occurrences of 2 by 2. in order to enforce floating point division.
Your link to ideone is Python 2.x and apparently so is your codeacademy interpreter.
import statistics as s
def mid(data):
return(int(s.median(data)))
middle = mid([3,4,6,3,12,6,45,32,78])
print(middle)
I'd use the statistics module. If you want your output to be an integer or a float, just cast it (float() or int() respectively).

How to convert an integer to variable length byte string?

I want to convert an integer (int or long) a big-endian byte string. The byte string has to be of variable length, so that only the minimum number of bytes are used (the total length length of the preceding data is known, so the variable length can be inferred).
My current solution is
import bitstring
bitstring.BitString(hex=hex(456)).tobytes()
Which obviously depends on the endianness of the machine and gives false results, because 0 bits are append and no prepended.
Does any one know a way to do this without making any assumption about the length or endianess of an int?
Something like this. Untested (until next edit). For Python 2.x. Assumes n > 0.
tmp = []
while n:
n, d = divmod(n, 256)
tmp.append(chr(d))
result = ''.join(tmp[::-1])
Edit: tested.
If you don't read manuals but like bitbashing, instead of the divmod caper, try this:
d = n & 0xFF; n >>= 8
Edit 2: If your numbers are relatively small, the following may be faster:
result = ''
while n:
result = chr(n & 0xFF) + result
n >>= 8
Edit 3: The second method doesn't assume that the int is already bigendian. Here's what happens in a notoriously littleendian environment:
Python 2.7 (r27:82525, Jul 4 2010, 09:01:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> n = 65539
>>> result = ''
>>> while n:
... result = chr(n & 0xFF) + result
... n >>= 8
...
>>> result
'\x01\x00\x03'
>>> import sys; sys.byteorder
'little'
>>>
A solution using struct and itertools:
>>> import itertools, struct
>>> "".join(itertools.dropwhile(lambda c: not(ord(c)), struct.pack(">i", 456))) or chr(0)
'\x01\xc8'
We can drop itertools by using a simple string strip:
>>> struct.pack(">i", 456).lstrip(chr(0)) or chr(0)
'\x01\xc8'
Or even drop struct using a recursive function:
def to_bytes(n):
return ([chr(n & 255)] + to_bytes(n >> 8) if n > 0 else [])
"".join(reversed(to_bytes(456))) or chr(0)
If you're using Python 2.7 or later then you can use the bit_length method to round the length up to the next byte:
>>> i = 456
>>> bitstring.BitString(uint=i, length=(i.bit_length()+7)/8*8).bytes
'\x01\xc8'
otherwise you can just test for whole-byteness and pad with a zero nibble at the start if needed:
>>> s = bitstring.BitString(hex=hex(i))
>>> ('0x0' + s if s.len%8 else s).bytes
'\x01\xc8'
I reformulated John Machins second answer in one line for use on my server:
def bytestring(n):
return ''.join([chr((n>>(i*8))&0xFF) for i in range(n.bit_length()/8,-1,-1)])
I have found that the second method, using bit-shifting, was faster for both large and small numbers, and not just small numbers.

Categories