It's my first question
So, the problem is python rounding. I have seen it, but I dont really know how to get around it.
For example: i have the number 10.34 - I need to receive just fractional part, so 0.34
I had some ideas how to do that. One of this:
n = float(input())
print(n - int(n))
In case of 10.34 the code give me "0.33999999999999986" instead 0.34.
I have some ideas how to do it with help of strings or another tools, but the task assumes that I need just some basic tools
Use round:
res = n - int(n)
print(round(res, 10))
n = float(input()) n = n - int(n) n = round(n,2)
https://www.w3schools.com/python/ref_func_round.asp
The round() function returns a floating point number that is a rounded version of the specified number, with the specified number of decimals.
round(number, digits)
For your refrence
Related
I have a float and would like to limit to just two decimals.
I've tried format(), and round(), and still just get 0, or 0.0
x = 8.972990688205408e-05
print ("x: ", x)
print ("x using round():", round(x))
print ("x using format():"+"{:.2f}".format(x))
output:
x: 8.972990688205408e-05
x using round(): 0
x using format():0.00
I'm expecting 8.98, or 8.97 depending on what method used. What am I missing?
You are using the scientific notation. As glhr pointed out in the comments, you are trying to round 8.972990688205408e-05 = 0.00008972990688205408. This means trying to round as type float will only print the first two 0s after the decimal points, resulting in 0.00. You will have to format via 0:.2e:
x = 8.972990688205408e-05
print("{0:.2e}".format(x))
This prints:
8.97e-05
You asked in one of your comments on how to get only the 8.97.
This is the way to do it:
y = x*1e+05
print("{0:.2f}".format(y))
output:
8.97
In python (and many other programming language), any number suffix with an e with a number, it is power of 10 with the number.
For example
8.9729e05 = 8.9729 x 10^3 = 8972.9
8.9729e-05 = 8.9729 x 10^-3 = 0.000089729
8.9729e0 = 8.9729 x 10^0 = 8.9729
8.972990688205408e-05 8.972990688205408 x 10^-5 = 0.00008972990688205408
8.9729e # invalid syntax
As pointed out by other answer, if you want to print out the exponential round up, you need to use the correct Python string format, you have many choices to choose from. i.e.
e Floating point exponential format (lowercase, precision default to 6 digit)
e Floating point exponential format (uppercase, precision default to 6 digit).
g Same as "e" if exponent is greater than -4 or less than precision, "f" otherwise
G Same as "E" if exponent is greater than -4 or less than precision, "F" otherwise
e.g.
x = 8.972990688205408e-05
print('{:e}'.format(x)) # 8.972991e-05
print('{:E}'.format(x)) # 8.972991E-05
print('{:.2e}'.format(x)) # 8.97e-05
(Update)
OP asked a way to remove the exponent "E" number. Since str.format() or "%" notation just output a string object, break the "e" notation out of the string will do the trick.
'{:.2e}'.format(x).split("e") # ['8.97', '-05']
print('{:.2e}'.format(x).split('e')[0]) # 8.97
If I understand correctly, you only want to round the mantissa/significand? If you want to keep x as a float and output a float, just specify the precision when calling round:
x = round(8.972990688205408e-05,7)
Output:
8.97e-05
However, I recommend converting x with the decimal module first, which "provides support for fast correctly-rounded decimal floating point arithmetic" (see this answer):
from decimal import Decimal
x = Decimal('8.972990688205408e-05').quantize(Decimal('1e-7')) # output: 0.0000897
print('%.2E' % x)
Output:
8.97E-05
Or use the short form of the format method, which gives the same output:
print(f"{x:.2E}")
rount() returns closest multiple of 10 to the power minus ndigits,
so there is no chance you will get 8.98 or 8.97. you can check here also.
I'd like to put a number to some power, then multiply it with another number and lastly mod it.
Python's pow function, that takes 3 parameters can't be used for my use-case scenario, so I'm trying to find fast alternative.
Examples:
I know I can do
9^10%2
as
pow(9, 10, 2)
but I can't do
(8*9^10)%2
with the same function
I've already tried using(numbers only for reference, real numbers a lot bigger)
pow(9, 10)*8 % 2 # tooks too long
pow(9, 10, 2)*8 # returns wrong answer
I'd like my numbers to be calculated really fast, even if they're up to 10^18. My time requirement is 2s for 20 of those numbers.
None of the above solutions didn't really work for me, either they were too slow or didn't return correct answer.
Your second solution contains an incorrect assumption that the following is true. Intuitively, it cannot be true because the first expression could be as large as c*(n-1), but the second must be strictly less than n
((a^b)%n)*c == (c*a^b))%n
The correct identity from Wikipedia:
ab mod n = [(a mod n)(b mod n)] mod n.
We can generalize this by induction (proof is left as an exercise to the reader):
So your expression should be:
(pow(9, 10, 2) * (8 % 2)) % 2
# OR
(pow(9, 10, 2) * 8) % 2
I have the following array in python
n = [565387674.45, 321772103.48,321772103.48, 214514735.66,214514735.65,
357524559.41]
if I sum all these elements, I get this:
sum(n)
1995485912.1300004
But, this sum should be:
1995485912.13
In this way, I know about floating point "error". I already used the isclose() function from numpy to check the corrected value, but
how much is this limit? Is there any way to reduce this "error"?
The main issue here is that the error propagates to other operations, for example, the below assertion must be true:
assert (sum(n) - 1995485911) ** 100 - (1995485912.13 - 1995485911) ** 100 == 0.
This is problem with floating point numbers. One solution is having them represented in string form and using decimal module:
n = ['565387674.45', '321772103.48', '321772103.48', '214514735.66', '214514735.65',
'357524559.41']
from decimal import Decimal
s = sum(Decimal(i) for i in n)
print(s)
Prints:
1995485912.13
You could use round(num, n) function which rounds the number to the desired decimal places. So in your example you would use round(sum(n), 2)
Why does the math module return the wrong result?
First test
A = 12345678917
print 'A =',A
B = sqrt(A**2)
print 'B =',int(B)
Result
A = 12345678917
B = 12345678917
Here, the result is correct.
Second test
A = 123456758365483459347856
print 'A =',A
B = sqrt(A**2)
print 'B =',int(B)
Result
A = 123456758365483459347856
B = 123456758365483467538432
Here the result is incorrect.
Why is that the case?
Because math.sqrt(..) first casts the number to a floating point and floating points have a limited mantissa: it can only represent part of the number correctly. So float(A**2) is not equal to A**2. Next it calculates the math.sqrt which is also approximately correct.
Most functions working with floating points will never be fully correct to their integer counterparts. Floating point calculations are almost inherently approximative.
If one calculates A**2 one gets:
>>> 12345678917**2
152415787921658292889L
Now if one converts it to a float(..), one gets:
>>> float(12345678917**2)
1.5241578792165828e+20
But if you now ask whether the two are equal:
>>> float(12345678917**2) == 12345678917**2
False
So information has been lost while converting it to a float.
You can read more about how floats work and why these are approximative in the Wikipedia article about IEEE-754, the formal definition on how floating points work.
The documentation for the math module states "It provides access to the mathematical functions defined by the C standard." It also states "Except when explicitly noted otherwise, all return values are floats."
Those together mean that the parameter to the square root function is a float value. In most systems that means a floating point value that fits into 8 bytes, which is called "double" in the C language. Your code converts your integer value into such a value before calculating the square root, then returns such a value.
However, the 8-byte floating point value can store at most 15 to 17 significant decimal digits. That is what you are getting in your results.
If you want better precision in your square roots, use a function that is guaranteed to give full precision for an integer argument. Just do a web search and you will find several. Those usually do a variation of the Newton-Raphson method to iterate and eventually end at the correct answer. Be aware that this is significantly slower that the math module's sqrt function.
Here is a routine that I modified from the internet. I can't cite the source right now. This version also works for non-integer arguments but just returns the integer part of the square root.
def isqrt(x):
"""Return the integer part of the square root of x, even for very
large values."""
if x < 0:
raise ValueError('square root not defined for negative numbers')
n = int(x)
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = (1 << (a+b)) - 1
while True:
y = (x + n//x) // 2
if y >= x:
return x
x = y
If you want to calculate sqrt of really large numbers and you need exact results, you can use sympy:
import sympy
num = sympy.Integer(123456758365483459347856)
print(int(num) == int(sympy.sqrt(num**2)))
The way floating-point numbers are stored in memory makes calculations with them prone to slight errors that can nevertheless be significant when exact results are needed. As mentioned in one of the comments, the decimal library can help you here:
>>> A = Decimal(12345678917)
>>> A
Decimal('123456758365483459347856')
>>> B = A.sqrt()**2
>>> B
Decimal('123456758365483459347856.0000')
>>> A == B
True
>>> int(B)
123456758365483459347856
I use version 3.6, which has no hardcoded limit on the size of integers. I don't know if, in 2.7, casting B as an int would cause overflow, but decimal is incredibly useful regardless.
Heron's method generates a sequence of numbers that represent better and better approximations for √n. The first number in the sequence is an arbitrary guess; every other number in the sequence is obtained from the previous number prev using the formula:
(1/2)*(prev+n/prev)
I am supposed to write a function heron() that takes as input two numbers: n and error. The function should start with an initial guess of 1.0 for √n and then repeatedly generate better approximations until the difference (more precisely, the absolute value of the difference) between successive approximations is at most error.
usage:
>>> heron(4.0, 0.5)
2.05
>>> heron(4.0, 0.1)
2.000609756097561
this is a bit tricky, but I will need to keep track of four variables:
# n, error, prev and current
I will also need a while loop with the condition:
((current - prev) > error):
A general rule for the while loop is that:
# old current goes into new prev
So this is what I got so far, it's not much because to start with I don't know how to incorporate the 'if' statement under the while loop.
def heron(n, error):
guess = 1
current = 1
prev = 0
while (current - prev) > error:
previous==1/2*(guess+n/guess):
print (previous) # just a simple print statement
# in order to see what i have so far
Can someone give me a few pointers in the right direction please?
thank you
If you don't want to use generators then the simplest would be:
def heron(n, error):
prev, new = 1.0, 0.5 * (1 + n)
while abs(new - prev) > error:
prev, new = new, 0.5 * (new + n/new)
return new
You can also generate an "infinite" sequence of heron numbers:
def heron(n):
prev = 1.0
yield prev, float('inf')
while True:
new = 0.5 * (prev + n/prev)
error = new - prev
yield new, error
prev = new
Now you can print so many numbers as you like, for example:
list(islice(heron(2), 3)) # First 3 numbers and associated errors
Generate as long as the error is greater than 0.01:
list(takewhile(lambda x:x[1] > 0.01, heron(2)))
Just to build on #elyase's answer, here's how you would get the arbitrary precision square root from the heron number generator they have provided. (the generator just gives the next number in the heron sequence)
def heron(n): ### posted by elyase
a = 1.0
yield a
while True:
a = 0.5 * (a + n/a)
yield a
def sqrt_heron(n, err):
g = heron(n)
prev = g.next()
current = g.next()
while( (prev - current) > err):
prev = current
current = g.next()
print current, prev
return current
print sqrt_heron(169.0,0.1)
Aside from python syntax, the thing that may be messing you up is that you need two guesses calculated from your initial guess to get started, and you compare how far apart these two guesses are. The while condition should be (prev - current) > err not (current - prev) > err since we expect the previous guess to be closer to the square (and therefore larger) than the current guess which should be closer to the square root. Since the initial guess could be any positive number, we need to calculate two iterations from it, to ensure that current will be less than prev.
The other answers up as I write this are using a Python generator function. I love generators but those are overkill for this simple problem. Below, solutions with simple while loops.
Comments below the code. heron0() is what you asked for; heron() is my suggested version.
def heron0(n, error):
guess = 1.0
prev = 0.0
while (guess - prev) > error:
prev = guess
guess = 0.5*(guess+n/guess)
print("DEBUG: New guess: %f" % guess)
return guess
def _close_enough(guess, n, allowed_error):
low = n - allowed_error
high = n + allowed_error
return low <= guess**2 <= high
def heron(n, allowed_error):
guess = 1.0
while not _close_enough(guess, n, allowed_error):
guess = 0.5*(guess+n/guess)
print("DEBUG: New guess: %f" % guess)
return guess
print("Result: %f" % heron0(4, 1e-6))
print("Result: %f" % heron(4, 1e-6))
Comments:
You don't really need both guess and current. You can use guess to hold the current guess.
I don't know why you were asking about putting an if statement in the while loop. In the first place, it is easy: you just put it in, and indent the statement(s) that are under the if. In the second place, this problem doesn't need it.
It's easy and fast to detect whether guess is close to prev. But I think for numerical accuracy, it would be better to directly test how good a square root guess actually is. So, square the value of guess and see if that is close to n. See how in Python it is legal to test whether a value is, at the same time, greater than or equal to a lower value and also less than or equal to a high value. (The alternate way to check: abs(n - guess**2) <= allowed_error)
In Python 2.x, if you divide an integer by an integer you will probably get an integer result. Thus 1/2 can very possibly have a result of 0. There are a couple of ways to fix that, or you can run your program in Python 3.x which guarantees that 1/2 returns 0.5, but it's simple to make your starting value for guess be a floating-point number.
I think this meets your requirements (note: I wrote it with python 2.7.10): it doesn't assume a guess of 1 and it takes takes 'num' and 'tolerance' as arguments for 'n' and 'error'. Also, it doesn't use variables "prev" and "current" or a while loop - are those part of your requirements, or your thoughts regarding a solution?
def heron(num, guess, tolerance):
if guess**2 != num:
##print "guess =", guess
if abs(float(num) - float(guess)**2) > float(tolerance):
avg_guess = 0.5 * (float(guess) + (float(num) / float(guess)))
return heron(num, avg_guess, tolerance)
print "Given your tolerance, this is Heron's best guess:", guess
else:
print guess, "is correct!"
Uncomment the print cmd if you want to see the progression of guesses.
I was dealing with the same problem and not many tools to solve it since my knowledge in Python is very limited.
I came up with this solution that is not very elegant nor advanced, but it solves the problem using Heron's algorithm. Just want it to share it here:
print("Please enter a positive integer 'x' to find its square root.")
x = int(input("x ="))
g = int(input("What's your best guess: "))
results = [g]
if g * g == x:
print("Good guess! The square root of", x, "is", g)
else:
g = (g + (x / g)) / 2
results.append(g)
while results[-1] != results[-2]:
g = (g + (x / g)) / 2
results.append(g)
else:
print(results)
print("Not quite. The square root of", x, "is", results[-1])