How to have an algorithm round in a "smart" way automatically - python-3.x

I would like to round number in a code but in a way that it adapts to each values.
For example i would like a rounding algorithm to return :
0.999999 it should return 1
0.0749999 it should return 0.075
0.006599 it should return 0.0066
and so on ...
I don't know in advance the number of digits (which is kinda my problem)
I was thinking to use strings to find where are the 9s (or count the 0s) but it is quite a lot of effort for that i was thinking ?
If you know any way to do that (if possible without advanced libraries) i would appreciate.
Thanks.

It's some complicated. but, It works. Please make sure the result is what you want. I think you can understand how to round the number from code.
def clear9(numstr):
liststr = list(numstr)
for index in range(len(liststr)-1,-1,-1):
if liststr[index] == '.': continue
if liststr[index] == '9':
liststr[index] = '0'
if index == 0:
liststr.insert(0, '1')
else:
if index != len(liststr)-1:
liststr[index] = str(int(liststr[index])+1)
break
numstr = ''
for item in liststr:
numstr += item
return numstr
def myround(num):
numstr = str(num)
numstr = clear9(numstr)
return float(numstr)
print (myround(9.05))
print (myround(9.999999))
print (myround(0.999999))
print (myround(0.0749999))
print (myround(0.006599))
print (myround(0.00659923))
print (myround(0.09659923))
print (myround(-0.00659923))
9.05
10.0
1.0
0.075
0.0066
0.00659923
0.09659923
-0.00659923

import math
def round_(number):
dist = int(math.log10(abs(number))) #number of zeros after decimal point
return (round(number, abs(dist) + 2) if dist != 0 else round(number))
print(round_(0.999999))
print(round_(0.0749999))
print(round_(0.006599))
print(round_(-0.00043565))
output:
1
0.075
0.0066
-0.00044

Dealing with floating point numbers is tricky. You want to do a kind of round-off in base 10, but floating point numbers are base 2.
So I propose to use the decimal module, which can represent real numbers exactly, as opposed to base-2 floating point.:
from decimal import Decimal
def myround(num):
dec = Decimal(num)
adj = abs(dec.adjusted())+1
return round(num, adj)
Look at the documentation for Decimal.adjusted() to understand how this works.
A test:
In [1]: from decimal import Decimal
In [2]: def myround(num):
...: dec = Decimal(num)
...: adj = abs(dec.adjusted())+1
...: return round(num, adj)
...:
In [3]: myround(0.999999)
Out[3]: 1.0
In [4]: myround(0.006599)
Out[4]: 0.0066
In [5]: myround(0.0749999)
Out[5]: 0.075

Related

how to change this code that use xrange to run in python 3?

I'm reading the High-Performance Python book from O'Reilly collection, in the page number 11 I found this code that works for python 2, the point here is to make one instruction that performs(by vectorizing) several at the same time
import math
def check_prime(number):
sqrt_number = math.sqrt(number)
number_float = float(number)
numbers = range(2, int(sqrt_number)+1)
for i in xrange(0, len(numbers), 5):
# the following line is not valid Python code
result = (number_float / numbers[i:(i+5)]).is_integer()
if any(result):
return False
return True
but I get this error
TypeError: unsupported operand type(s) for /: 'float' and 'list'
I've tried to change it to work on python 3 here is my try:
import math
def check_prime(number):
sqrt_number = math.sqrt(number)
number_float = float(number)
numbers = list(range(2, int(sqrt_number)+1))
for i in range(0, len(numbers), 5):
# the following line is not valid Python code
result = (number_float / numbers[i:(i+5)]).is_integer()
if any(result):
return False
return True
I changed the xrange for range and the range(2, int(sqrt_number)+1) for list(range(2, int(sqrt_number)+1)) but i did not have succeed in this. I suppose there is a special operator for sets or something like that but have no idea. if any of you people can help me I'll be so grateful whit you
I looked at the book and that line is not supposed to actually work as is; you cannot divide by a list in Python. The author uses that code as an example of what vectorization would look like. The # the following line is not valid Python code comment is in the original to indicate that.
The closest in term of functionality and semantics would probably be this code:
import math
def check_prime(number):
sqrt_number = math.sqrt(number)
number_float = float(number)
numbers = list(range(2, int(sqrt_number)+1))
for i in range(0, len(numbers), 5):
# the following line is now valid Python code, but not vectorized
result = [(number_float / n).is_integer for n in numbers[i:(i+5)]]
if any(result):
return False
return True
Note that the processing for result in this version is not done in parallel, so it's probably not what the author wanted to demonstrate. As far as I know, vectorization isn't natively available in Python, you would have to use numpy to do it. This article should be useful if you want to try it.
Try this:
import math
def check_prime(number):
sqrt_number = math.sqrt(number)
number_float = float(number)
numbers = list(range(2, int(sqrt_number)+1))
for i in range(0, len(numbers), 5):
result = [number_float % num == 0 for num in numbers[i:(i+5)]]
if any(result):
return False
return True

integer and floating result from multiplication in python [duplicate]

This question already has answers here:
Formatting floats without trailing zeros
(21 answers)
Closed 2 years ago.
In the same function, I have tried to use integer, float, and rounding, but I could not get this result. What did I do wrong?
The goal is:
10*12.3 = 123
3*12.3= 36.9
my code:
def multi(n1, n2):
x = n1*n2
return x
I have tried int(n1*n2), but I got 123 and 36. Then I tried float(n1*n2) and I got 123.0 and 36.9. What did I do wrong and how can I fix it?
You are always multiplying an integer with a float which will always output a float.
If you want the number that your function returns to be a float with 1 decimal point you can use round(num, 1).
def multi(n1, n2):
x = n1*n2
return round(x, 1)
print(multi(10, 12.3)) # outputs '123.0'
print(multi(3, 12.3)) # outputs '36.9'
To escape the .0 you could probably use an if statement although I don't see the use of it, since doing calculations with floats have the same output as integers (when they are .0)
def multi(n1, n2):
x = n1 * n2
return round(x, 1)
output = []
output.append(multi(10, 12.3)) # outputs '123.0'
output.append(multi(3, 12.3)) # outputs '36.9'
for index, item in enumerate(output):
if int(item) == float(item):
output[index] = int(item)
print(output) # prints [129, 36.9]
This should probably help you but it shouldn't matter all that match to you
The number is not the representation of the number. For example, all these representations are 123:
123
12.3E1
123.0
123.0000000000000000000
My advice is to do them as floating point and either use output formatting to get them all in a consistent format:
>>> for i in (12.3 * 10, 42., 36.9 / 10):
... print(f"{i:8.2f}")
...
123.00
42.00
3.69
or string manipulation to remove useless suffixes:
>>> import re
>>> x = 12.3 * 10
>>> print(x)
123.0
>>> print(re.sub(r"\.0*$", "", str(x)))
123

How to return floating values using floor division

In Python 3, I want to return the units place of an integer value, then tens, then hundreds and so on. Suppose I have an integer 456, first I want to return 6, then 5 then 4. Is there any way? I tried floor division and for loop but didn't work.
If you look at the list of basic operators from the documentation, for example here,
Operator Description Example
% Modulus Divides left hand operand by right hand operand and returns remainder b % a = 1
// Floor Division - The division of operands where the result is the quotient in which the digits after the decimal point are removed. But if one of the operands is negative, the result is floored, i.e., rounded away from zero (towards negative infinity): 9//2 = 4 and 9.0//2.0 = 4.0, -11//3 = -4, -11.0//3 = -4.0
With that knowledge, you can get what you want as follows:
In [1]: a = 456
In [2]: a % 10
Out[2]: 6
In [3]: (a % 100) // 10
Out[3]: 5
In [4]: a // 100
Out[4]: 4
Write a generator if you want to retrieve digits in different places of your code based on requirement as follows.
If you are not much familiar with Python's generator, have a quick look at https://www.programiz.com/python-programming/generator.
» Here get_digits() is a generator.
def get_digits(n):
while str(n):
yield n % 10
n = n // 10
if not n:
break
digit = get_digits(1729)
print(next(digit)) # 9
print(next(digit)) # 2
print(next(digit)) # 7
print(next(digit)) # 1
» If you wish to iterate over digits, you can also do so as follows.
for digit in get_digits(74831965):
print(digit)
# 5
# 6
# 9
# 1
# 3
# 8
# 4
# 7
» Quick overview about its usage (On Python3's Interactive terminal).
>>> def letter(name):
... for ch in name:
... yield ch
...
>>>
>>> char = letter("RISHIKESH")
>>>
>>> next(char)
'R'
>>>
>>> "Second letter is my name is: " + next(char)
'Second letter is my name is: I'
>>>
>>> "3rd one: " + next(char)
'3rd one: S'
>>>
>>> next(char)
'H'
>>>

Can't convert complex to float on python 3

I write this code for uri online judge(problem no.1036)...It is an Bhaskara's formula...
import cmath
A,B,C=input().split()
A = float(A)
B = float(B)
C = float(C)
D = (B*B)-(4*A*C)
if((D== -D)|(A==0)):
print("Impossivel calcular")
else:
T = cmath.sqrt(D)
x1 = (-B+T)/(2*A)
x2 = (-B-T)/(2*A)
print("R1 = %.5f" %x1)
print("R2 = %.5f" %x2)
but when i submit this program...that runtime error occured...
Traceback (most recent call last): File "Main.py", line 14, in
print("R1 = %.5f" %x1)
TypeError: can't convert complex to float
Command exited with non-zero status (1)
please help me to solve this problem.
The problem with using sqrt imported from cmath is that it outputs a complex number, which cannot be converted to float. If you are calculating a sqrt from positive number, use math library (see below).
>>> from cmath import sqrt
>>> sqrt(2)
(1.4142135623730951+0j)
>>> from math import sqrt
>>> sqrt(2)
1.4142135623730951
the problem is just that your format string is for floats and not for complex numbers. something like this will work:
print('{:#.3} '.format(5.1234 + 4.123455j))
# (5.12+4.12j)
or - more explicit:
print('{0.real:.3f} + {0.imag:.3f}i'.format(5.123456789 + 4.1234556547643j))
# 5.123 + 4.123i
you may want to have a look at the format specification mini language.
# as format specifier will not work with the old-style % formatting...
then there are more issues with your code:
if((D== -D)|(A==0)):
why not if D==0:? and for that it might be better to use cmath.isclose.
then: | is a bit-wise operator the way you use it; you may want to replace it with or.
your if statement could look like this:
if D == 0 or A == 0:
# or maybe
# if D.isclose(0) or A.isclose():

Program is written but cant get it to concatenate

This program takes 4 points on a graph and puts them into a Lagrange polynomial. I got my terms to output correctly but I need to concatenate the 4 terms into 1 line of code. No matter where I seem to try to concatenate, it keeps messing up the loops and therefore messing up my terms. I'm sure there is an easier way to do this, but I have to use strings and concatenation for my assignment. Any help would be appreciated. Thanks.
import string
from math import *
def main():
n=4
abscissa=[-5,-2,3,7]
ordinate=[4,-6,8,1]
for j in range(n):
LP=str(ordinate[j])
denom="1"
for k in range(n):
if k!=j:
denom= denom+"*("+str(abscissa[j])+"-"+str(abscissa[k])+")"
LP=LP+"*(x-"+str(abscissa[k])+")"
LP=LP+'/'+denom
print(LP)
main()
Collect the terms, and join them:
import string
from math import *
def main():
n=4
abscissa=[-5,-2,3,7]
ordinate=[4,-6,8,1]
result = ''
for j,y in enumerate(ordinate):
if j!=0:
result += '+'
LP=str(y)
denom="1"
for k,x in enumerate(abscissa):
if k!=j:
denom += '*({}-{})'.format(abscissa[j],x)
LP += '*(x-{})'.format(x)
LP += '/' + denom
result += LP
print(result)
main()

Resources