Convert to different positional notation in Python 3 - python

I'm trying to write a function that allows me to convert a number from a certain positional notation to another one of choice, from binary all the way to *hexa*trigesimal base numbers. In order to do so I first need to be able to convert my initial number (given as a string) to a decimal number to make further conversion easier.
However, my function appears to have a mistake.
What I have:
def decimal(number, base1):
number_dec = 0
val = '0123456789abcdefghijklmnopqrstuvwxyz'
if base1 != 10:
for digit in number[::-1]:
factor = val.find(digit)
for exp in range(0, len(number)):
number_dec += factor * base1 **exp
else:
number_dec = number
return number_dec
If I enter, for instance:
decimal('4d2', 16)
The function returns '5187' instead of the correct '1234'.
Where is the mistake?

You perform the entire loop for every digit:
for exp in range(0, len(number)):
number_dec += factor * base1 **exp
If you don't have to roll out your own, you could just use the built-in facility:
In [2]: int('4d2', 16)
Out[2]: 1234

Related

iterative function for calculating exponents without using **

I need to write a program where I write an iterative function that calculates the exponential of base * exponent without using ** operator in my program.
I have tried the code I have already created but am unsure how to fix my error of "int" object is not callable.
def iterPower (base, exp):
"""Run a program in which the base multiplies itself by the exponent value"""
exp = 3
for n in base(exp):
exp *= base
return exp
base = 5
exp = 3
print(iterPower(5,3))
The expected result would be the answer of 125, but I am not getting any number due to my errors.
You need to multyply base * base exp times:
def iterPower (base, exp):
"""Run a program ion which the base multiplies itself by the exponent value"""
n = base
for _ in range(1, exp):
n *= base
return n
Results:
>>> iterPower(5, 3)
125
>>> 5**3
125
Youre passing in integers so you can't call 5(3), like base(exp) does. Try using for n in range(exp) instead, it will give you the desired number of iterations.
Here is an answer using the "While" loop:
result = 1
while exp > 0:
result *= base
exp -= 1
return result

Round number with variable power to two digits accuracy [duplicate]

This question already has answers here:
How to round a number to significant figures in Python
(26 answers)
Closed 4 years ago.
I want a variable code which rounds for example 0.91823 to 0.92 , but the number 0.00009384 should be rounded to 0.000094. I guess it's easy, but I could not find something which does the job.
For clarity I'll keep the code expanded, rather than forcing it into a one-liner.
def round2(n, numberOfDigits):
p = floor(log10(n));
# normalize
n = n * pow(10, -p);
# round
n = (n - n % pow(10, numberOfDigits)) * pow(10, p);
# return
return n;
The idea is to first 'remove' all leading zeroes by multiplying the incoming number by an appropriate power of 10.
Then use the normal rounding operator to round the new number to the appropriate radix.
And finally scale the number again.
You can print the number to 2 digits of precision, then convert back to a float by specifying the required number of decimal places:
# Format the number to scientific notation with one digit before
# the decimal point and one after, then split the sctring into the mantissa
# and exponent.
a, b = ('{0:.1E}'.format(.0000004565)).split("E")
# If the exponent is -n, get the number of required decimal digits as n+1.
c=1-int(b)
# Set up a '%0.xf' format string where x is the required number of digits,
# and use that format to print the reassembled scientific notation value
res = ('%%0.%df' % c) % float(a+"E"+b)
This works with some numbers >1, but breaks down above 99.
You could try string-manipulation:
import re
def roundToDigit(number, numDigits):
# Convert number to a string
asStr = str(number)
# Search for the first numerical digit, ignoring zeros
m = re.search("[123456789]", asStr)
if (not m):
return round(0, numDigits)
afterDecimal = m.start()
# Check if the number is in scientific notation
isExp = asStr.find("e") > -1
if (isExp):
numZeros = int(asStr[ (asStr.find("-", 1) + 1) :])
return float(round(number, numZeros + numDigits - 1))
# Check for numbers > 9
beforeDecimal = asStr.find(".")
if (beforeDecimal == -1):
return float(round(number, numDigits))
return float(round(number, afterDecimal - beforeDecimal + numDigits - 1))
Using log is probably the correct choice but if, for whatever reason, that doesn't do it for you then this will work.

Unicode recursion for a number

I want to get any number. e.g: 14892. And return it as 25903
(according to each character's unicode value)
This is what I have so far:
def convert(n):
if len(n)>0:
x = (chr(ord(str((int(n[0])+1)))))
return x
def convert(n):
return int(''.join([str(int(elem)+1)[-1] for elem in str(n)]))
You could use a list comprehension.
To perform this transformation, you need to get each digit and add one to it, with 10 wrapping around to 0. The simple way to do that wrapping is to use the modulus operator. We can also use integer division and modulus to extract the digits, and we can do both operations using the built-in divmod function. We store the modified digits in a list, since the simple way to combine the digits back into a single number needs the digits in reverse order.
def convert(n):
a = []
while n:
n, r = divmod(n, 10)
a.append((r + 1) % 10)
n = 0
for u in reversed(a):
n = 10 * n + u
return n
# Test
print(convert(14892))
output
25903
That algorithm is fairly close to the usual way to do this transformation in traditional languages. However, in Python, it's actually faster to do this sort of thing using strings, since the str and int constructors can do most of their work at C speed. The resulting code is a little more cryptic, but much more compact.
def convert(n):
return int(''.join([str((int(c) + 1) % 10) for c in str(n)]))
You could convert the number to a string, use the translate function to swap out the numbers, and convert back to integer again:
>>> t=str.maketrans('1234567890','2345678901')
>>> x = 14892
>>> y = int(str(x).translate(t))
>>> y
25903

Failsafe doesn't execute correctly

I'm making a scientific notation writing program, so let me show you the code:
import time
def scientific_notation(number):
decimal = ""
for thing in str(number):
"""
Loops through the number to add stuff to "decimal"
(probably not necessary but i'm going to keep it
there in case I need a filter.)
"""
if len(decimal) == len(str(number)):
break
else:
decimal += thing
decimal = decimal.replace('0','')
print(decimal)
while float(decimal) > 10:
# Uses decimal notation
actual = ''
# To keep track of the original place
for x in range(0,len(str(number))):
actual += str(number)[x]
decimal = decimal.replace(str(number)[x],str(number)[x]+'.')
# Adding decimal points to each place until the float version of that is less than 10
if decimal.count('.') > 1:
# if there's more than one decimal, replace that value with what it was before
decimal = decimal.replace(str(number)[x],actual)
elif float(decimal) > 10:
# if the float version of the decimal is more than 10, wait for the while loop to realize that by doing nothing
pass
else:
pass
else:
# Output
power = '10^'+str(str(number).count('0'))
print(decimal+" * "+power)
scientific_notation(102)
Alright, now that you've looked at it let me tell you what's going on.
So, in the while loop, my if statement isn't executing
if decimal.count('.') > 1
or at least, not executing correctly and that's causing a
ValueError: could not convert string to float: '1.102.'
because my while loop tries to convert it to a float, but gets '1.102.' and raises a ValueError because you can't convert something with two decimal points into a float. Any ideas on why the if statement isn't working? I dunno, maybe i'm just being stupid.
Eek your code is scary, and does some unintended things right off the bat. For instance:
decimal = ""
for thing in str(number):
"""
Loops through the number to add stuff to "decimal"
(probably not necessary but i'm going to keep it
there in case I need a filter.)
"""
if len(decimal) == len(str(number)):
break
else:
decimal += thing
That is the same as
decimal = str(number)
also
decimal = decimal.replace('0','')
That turns 102 into 12 which can't be intentional.
Let's look at a different algorithm, and handle this with arithmetic instead of string manipulation.
def scientific_notation(number):
n = 0
while number > 10:
n += 1
number /= 10
print(f"{number} * 10^{n}")
>>> scientific_notation(102)
1.02 * 10^2

count number of ones in a given integer

How do you count the number of ones in a given integer's binary representation.
Say you are given a number 20, which is 10100 in binary, so number of ones is 2.
What you're looking for is called the Hamming weight, and there are a lot of algorithms to do it. Here's another straightforward one:
def ones(n):
w = 0
while (n):
w += 1
n &= n - 1
return w
Use the awesome collections module.
>>> from collections import Counter
>>> binary = bin(20)[2:]
>>> Counter(binary)
Counter({'0': 3, '1': 2})
Or you can use the built-in function count():
>>> binary = bin(20)[2:]
>>> binary.count('1')
2
Or even:
>>> sum(1 for i in bin(20)[2:] if i == '1')
2
But that last solution is slower than using count()
>>> num = 20
>>> bin(num)[2:].count('1')
2
The usual way to make this blinding fast is to use lookup tables:
table = [bin(i)[2:].count('1') for i in range(256)]
def pop_count(n):
cnt = 0
while n > 0:
cnt += table[n & 255]
n >>= 8
return cnt
In Python, any solution using bin and list.count will be faster, but this is nice if you want to write it in assembler.
The int type has a new method int.bit_count() since python 3.10a, returning the number of ones in the binary expansion of a given integer, also known as the population count as follows:
n = 20
bin(n)
'0b10100'
n.bit_count() returns 2 as it has 2 ones in the binary representation.
The str.count method and bin function make short work of this little challenge:
>>> def ones(x):
"Count the number of ones in an integer's binary representation"
return bin(x).count('1')
>>> ones(20)
2
You can do this using bit shifting >> and bitwise and & to inspect the least significant bit, like this:
def count_ones(x):
result = 0
while x > 0:
result += x & 1
x = x >> 1
return result
This works by shifting the bits right until the value becomes zero, counting the number of times the least significant bit is 1 along the way.
I am a new coder and I found this one logic simple. Might be easier for newbies to understand.
def onesInDecimal(n):
count = 0
while(n!=0):
if (n%2!=0):
count = count+1
n = n-1
n = n/2
else:
n = n/2
return count
For a special case when you need to check quickly whether the binary form of the integer x has only a single 1 (and thus is a power of 2), you can use this check:
if x == -(x | (-x)):
...
The expression -(x | (-x)) is the number that you get if you replace all 1s except the last one (the least significant bit) in the binary representation of x with 0.
Example:
12 = 1100 in binary
-12 = ...110100 in binary (with an infinite number of leading 1s)
12 | (-12) = ...111100 in binary (with an infinite number of leading 1s)
-(12 | (-12)) = 100 in binary
If the input number is 'number'
number =20
len(bin(number)[2:].replace('0',''))
Another solution is
from collections import Counter
Counter(list(bin(number))[2:])['1']

Categories

Resources