Rounding to 2 decimal places in Python - python

This isn't a duplicate because I have checked everything before this post on this site. I think I have managed to do the first two bullet points. The first one I will do through a string but I am willing to change that if you know another way. The 2nd one is using comma seperators for the $'s. So I will use a float but once again am willing to change if better way is found.
But I am stuck.
And the "print("%.2f") % str) is something I found but I need work on rounding to two decimal spaces and the last bullet point.
Code:
import random
def random_number():
random_dollars = random.uniform(1.00, 10000.00)
print(round(random_dollars, 2))
print("%.2f") % str
print(random_number())
Shell:
C:\Users\jacke\PycharmProjects\ASLevelHomeworkWeek18\venv\Scripts\python.exe C:/Users/jacke/PycharmProjects/ASLevelHomeworkWeek18/ASLevelHomeworkWeek18.py 6567.62 Traceback (most recent call last): %.2f File
C:/Users/jacke/PycharmProjects/ASLevelHomeworkWeek18/ASLevelHomeworkWeek18.py", line 10, in <module> print(random_number()) File
C:/Users/jacke/PycharmProjects/ASLevelHomeworkWeek18/ASLevelHomeworkWeek18.py", line 7, in random_number print("%.2f") % str TypeError: unsupported operand type(s) for %: 'NoneType' and 'type' Process finished with exit code 1

You can format currency like this:
def random_number():
random_dollars = random.uniform(1, 10000)
result = '$ {:0>9}'.format('{:,.2f}'.format(random_dollars))
print(result)
{:0>10} means: pad string left to width 9 with 0's.
{:,.2f} rounds to two decimal places (.2f) and adds a comma as thousands-separator.
Just one side note: by using random.uniform(1, 10000) most of your numbers will be large (>1000), if you want to test your script with small amounts you could use random_dollars = 10**random.uniform(0, 4) instead:
def random_number():
random_dollars = 10**random.uniform(0, 4)
result = '$ {:0>9}'.format('{:,.2f}'.format(random_dollars))
print(result)

If I get what you are saying you want to round a number to 2 decimal places. Here is how I would do it.
import random
def random_number():
random_dollars = random.uniform(1, 10000)
split = str(random_dollars).split(".")
if (len(split) == 2 ):
if (len(split[1]) == 1 ):# checks if 1 digit after decimal place
answer = split[0] + ".0"
split[1] = str(int(int(split[1]) / (10 ** (len(split[1]) - 3) )))
# Gets 3 decimal places
if int(split[1][-1:]) => 5: #Checks if last digit is above or equal to 5
split[1] = int(split[1][:-1])
split[1] += 1
else:
split[1] = int(split[1][:-1])
answer = split[0] + '.' + str(split[1])
else:
answer = split[0] + ".00"
print(answer)
random_number()
This makes it so if the random number is somehow 100 it will add 2 zeros. If the number is like 100.1 it will add one zero. It will also round it.

def random_number():
random_dollars = random.uniform (1.00, 10000.00)
n = round(random_dollars,2)
bd, d = str(n).split('.')
if len(d) == 1:
n = bd + "." + d + '0'
return n
else:
return n
for i in range(1, 20):
print(random_number())
7340.55
7482.70
3956.81
3044.50
4108.57
4864.90
235.00
9831.98
960.97
1172.28
5221.31
3663.50
5410.50
3448.52
8288.13
293.48
1390.68
9216.15
6493.65

TL;DR: you have to put the % directly after the string and you have to put a real variable there, not the type str
from the last line of your error message you can see that the problem is the % operator. You can also see that it tried to do the operation with two objects of types 'NoneType' and 'type'. Since you put the entire print statement in front of the % and print returns None (which is of type NoneType), the first operand is of type NoneType. then, the second operand is the type str, which is, as just said, a type. You can fix this by moving the % operator after the string and replacing str with your variable random_dollars since that is what you want to insert into the string.
import random
def random_number():
random_dollars = random.uniform(1.00, 10000.00)
print(round(random_dollars, 2))
# this:
print("%.2f" % random_dollars)
print(random_number())

Related

int 111 to binary 111(decimal 7)

Problem:Take a number example 37 is (binary 100101).
Count the binary 1s and create a binary like (111) and print the decimal of that binary(7)
num = bin(int(input()))
st = str(num)
count=0
for i in st:
if i == "1":
count +=1
del st
vt = ""
for i in range(count):
vt = vt + "1"
vt = int(vt)
print(vt)
I am a newbie and stuck here.
I wouldn't recommend your approach, but to show where you went wrong:
num = bin(int(input()))
st = str(num)
count = 0
for i in st:
if i == "1":
count += 1
del st
# start the string representation of the binary value correctly
vt = "0b"
for i in range(count):
vt = vt + "1"
# tell the `int()` function that it should consider the string as a binary number (base 2)
vt = int(vt, 2)
print(vt)
Note that the code below does the exact same thing as yours, but a bit more concisely so:
ones = bin(int(input())).count('1')
vt = int('0b' + '1' * ones, 2)
print(vt)
It uses the standard method count() on the string to get the number of ones in ones and it uses Python's ability to repeat a string a number of times using the multiplication operator *.
Try this once you got the required binary.
def binaryToDecimal(binary):
binary1 = binary
decimal, i, n = 0, 0, 0
while(binary != 0):
dec = binary % 10
decimal = decimal + dec * pow(2, i)
binary = binary//10
i += 1
print(decimal)
In one line:
print(int(format(int(input()), 'b').count('1') * '1', 2))
Let's break it down, inside out:
format(int(input()), 'b')
This built-in function takes an integer number from the input, and returns a formatted string according to the Format Specification Mini-Language. In this case, the argument 'b' gives us a binary format.
Then, we have
.count('1')
This str method returns the total number of occurrences of '1' in the string returned by the format function.
In Python, you can multiply a string times a number to get the same string repeatedly concatenated n times:
x = 'a' * 3
print(x) # prints 'aaa'
Thus, if we take the number returned by the count method and multiply it by the string '1' we get a string that only contains ones and only the same amount of ones as our original input number in binary. Now, we can express this number in binary by casting it in base 2, like this:
int(number_string, 2)
So, we have
int(format(int(input()), 'b').count('1') * '1', 2)
Finally, let's print the whole thing:
print(int(format(int(input()), 'b').count('1') * '1', 2))

Is it possible to convert a really large int to a string quickly in python

I am building an encryption program which produces a massive integer.It looks something like this:
a = plaintextOrd**bigNumber
when i do
a = str(a)
it takes over 28 minutes.
Is there any possible way to convert an integer like this quicker that using the built in str() function?
the reason i need it to be a string is because of this function here:
def divideStringIntoParts(parts,string):
parts = int(parts)
a = len(string)//parts
new = []
firstTime = True
secondTime = True
for i in range(parts):
if firstTime:
new.append(string[:a])
firstTime = False
elif secondTime:
new.append(string[a:a+a])
secondTime = False
else:
new.append(string[a*i:a*(i+1)])
string2 = ""
for i in new:
for i in i:
string2 += i
if len(string2) - len(string) != 0:
lettersNeeded = len(string) - len(string2)
for i in range(lettersNeeded):
new[-1] += string[len(string2) + i]
return new
You wrote in the comments that you want to get the length of the integer in decimal format. You don't need to convert this integer to a string, you can use "common logarithm" instead:
import math
math.ceil(math.log(a, 10))
Moreover, if you know that:
a = plaintextOrd**bigNumber
then math.log(a, 10) is equal to math.log(plaintextOrd, 10) * bigNumber, which shouldn't take more than a few milliseconds to calculate:
>>> plaintextOrd = 12345
>>> bigNumber = 67890
>>> a = plaintextOrd**bigNumber
>>> len(str(a))
277772
>>> import math
>>> math.ceil(math.log(a, 10))
277772
>>> math.ceil(math.log(plaintextOrd, 10) * bigNumber)
277772
It should work even if a wouldn't fit on your hard drive:
>>> math.ceil(math.log(123456789, 10) * 123456789012345678901234567890)
998952457326621672529828249600
As mentioned by #kaya3, Python standard floats aren't precise enough to describe the exact length of such a large number.
You could use mpmath (arbitrary-precision floating-point arithmetic) to get results with the desired precision:
>>> from mpmath import mp
>>> mp.dps = 1000
>>> mp.ceil(mp.log(123456789, 10) * mp.mpf('123456789012345678901234567890'))
mpf('998952457326621684655868656199.0')
Some quick notes on the "I need it for this function".
You don't need the first/second logic:
[:a] == [a*0:a*(0+1)]
[a:a+a] == [a*1:a*(1+1)]
So we have
new = []
for i in range(parts):
new.append(string[a*i:a*(i+1)])
or just new = [string[a*i:a*(i+1)] for i in range(parts)].
Note that you have silently discarded the last len(string) % parts characters.
In your second loop, you shadow i with for i in i, which happens to work but is awkward and dangerous. It can also be replaced with string2 = ''.join(new), which means you can just do string2 = string[:-(len(string) % parts)].
You then see if the strings are the same length, and then add the extra letters to the end of the last list. This is a little surprising, e.g. you would have
>>> divideStringIntoParts(3, '0123456789a')
['012', '345', '6789a']
When most algorithms would produce something that favors even distributions, and earlier elements, e.g.:
>>> divideStringIntoParts(3, '0123456789a')
['0124', '4567', '89a']
Regardless of this, we see that you don't really care about the value of the string at all here, just how many digits it has. Thus you could rewrite your function as follows.
def divide_number_into_parts(number, parts):
'''
>>> divide_number_into_parts(12345678901, 3)
[123, 456, 78901]
'''
total_digits = math.ceil(math.log(number + 1, 10))
part_digits = total_digits // parts
extra_digits = total_digits % parts
remaining = number
results = []
for i in range(parts):
to_take = part_digits
if i == 0:
to_take += extra_digits
digits, remaining = take_digits(remaining, to_take)
results.append(digits)
# Reverse results, since we go from the end to the beginning
return results[::-1]
def take_digits(number, digits):
'''
Removes the last <digits> digits from number.
Returns those digits along with the remainder, e.g.:
>>> take_digits(12345, 2)
(45, 123)
'''
mod = 10 ** digits
return number % mod, number // mod
This should be very fast, since it avoids strings altogether. You can change it to strings at the end if you'd like, which may or may not benefit from the other answers here, depending on your chunk sizes.
Faster than function str conversion of int to str is provided by GMPY2
Source of Example Below
import time
from gmpy2 import mpz
# Test number (Large)
x = 123456789**12345
# int to str using Python str()
start = time.time()
python_str = str(x)
end = time.time()
print('str conversion time {0:.4f} seconds'.format(end - start))
# int to str using GMPY2 module
start = time.time()
r = mpz(x)
gmpy2_str = r.digits()
end = time.time()
print('GMPY2 conversion time {0:.4f} seconds'.format(end - start))
print('Length of 123456789**12345 is: {:,}'.format(len(python_str)))
print('str result == GMPY2 result {}'.format(python_str==gmpy2_str))
Results (GMPY2 was 12 times faster in test)
str conversion time 0.3820 seconds
GMPY2 conversion time 0.0310 seconds
Length of 123456789**12345 is: 99,890
str result == GMPY2 result True

python script giving typerror on nested if statements

I'm trying to write a simple multiplication program first time in python and I get the following error, not sure why. My code is also posted below.
#!/usr/bin/env python
from math import *
def main():
multiplier = raw_input('multiplier?')
multiplicand = raw_input('multiplicand?')
print (recursive(multiplier, multiplicand))
def recursive(multiplier, multiplicand):
if (multiplier == 0):
answer = 0
if (multiplier == 1):
answer = multiplicand
if ((multiplier > 1) & ((multiplier % 2) == 0)):
answer = recursive((multiplier/2), (multiplicand*2))
if ((multiplier > 1) & ((multiplier % 2) == 1)):
answer = (multiplicand + (recursive((multiplier/2), (multiplicand*2))))
return answer
main()
Error:
multiplier?5
multiplicand?5
Traceback (most recent call last):
File "./multiplication.py", line 20, in <module>
main()
File "./multiplication.py", line 7, in main
print (recursive(multiplier, multiplicand))
File "./multiplication.py", line 14, in recursive
if ((multiplier > 1) & ((multiplier % 2) == 0)):
TypeError: not all arguments converted during string formatting
Multiplier is a string so the modulus operator is attempting to put a value in the string here like you'd see in a string string = "%s%d...". Hence the conversion error. Instead of a doing a mod operation. You need to convert the variable multiplier to an int (or float).
multiplier is being passed as a string, not a number. This is because raw_input() always returns a string. To convert it, do float(raw_input()).
The error is because the % operator returns the remainder for two numbers, but your string isn't a valid format string.
7 % 2 == 1
but it does string formatting when the first one is a string
'%d dogs ' % 2 == '2 dogs'

Find length of a string that includes its own length?

I want to get the length of a string including a part of the string that represents its own length without padding or using structs or anything like that that forces fixed lengths.
So for example I want to be able to take this string as input:
"A string|"
And return this:
"A string|11"
On the basis of the OP tolerating such an approach (and to provide an implementation technique for the eventual python answer), here's a solution in Java.
final String s = "A String|";
int n = s.length(); // `length()` returns the length of the string.
String t; // the result
do {
t = s + n; // append the stringified n to the original string
if (n == t.length()){
return t; // string length no longer changing; we're good.
}
n = t.length(); // n must hold the total length
} while (true); // round again
The problem of, course, is that in appending n, the string length changes. But luckily, the length only ever increases or stays the same. So it will converge very quickly: due to the logarithmic nature of the length of n. In this particular case, the attempted values of n are 9, 10, and 11. And that's a pernicious case.
A simple solution is :
def addlength(string):
n1=len(string)
n2=len(str(n1))+n1
n2 += len(str(n2))-len(str(n1)) # a carry can arise
return string+str(n2)
Since a possible carry will increase the length by at most one unit.
Examples :
In [2]: addlength('a'*8)
Out[2]: 'aaaaaaaa9'
In [3]: addlength('a'*9)
Out[3]: 'aaaaaaaaa11'
In [4]: addlength('a'*99)
Out[4]: 'aaaaa...aaa102'
In [5]: addlength('a'*999)
Out[5]: 'aaaa...aaa1003'
Here is a simple python port of Bathsheba's answer :
def str_len(s):
n = len(s)
t = ''
while True:
t = s + str(n)
if n == len(t):
return t
n = len(t)
This is a much more clever and simple way than anything I was thinking of trying!
Suppose you had s = 'abcdefgh|, On the first pass through, t = 'abcdefgh|9
Since n != len(t) ( which is now 10 ) it goes through again : t = 'abcdefgh|' + str(n) and str(n)='10' so you have abcdefgh|10 which is still not quite right! Now n=len(t) which is finally n=11 you get it right then. Pretty clever solution!
It is a tricky one, but I think I've figured it out.
Done in a hurry in Python 2.7, please fully test - this should handle strings up to 998 characters:
import sys
orig = sys.argv[1]
origLen = len(orig)
if (origLen >= 98):
extra = str(origLen + 3)
elif (origLen >= 8):
extra = str(origLen + 2)
else:
extra = str(origLen + 1)
final = orig + extra
print final
Results of very brief testing
C:\Users\PH\Desktop>python test.py "tiny|"
tiny|6
C:\Users\PH\Desktop>python test.py "myString|"
myString|11
C:\Users\PH\Desktop>python test.py "myStringWith98Characters.........................................................................|"
myStringWith98Characters.........................................................................|101
Just find the length of the string. Then iterate through each value of the number of digits the length of the resulting string can possibly have. While iterating, check if the sum of the number of digits to be appended and the initial string length is equal to the length of the resulting string.
def get_length(s):
s = s + "|"
result = ""
len_s = len(s)
i = 1
while True:
candidate = len_s + i
if len(str(candidate)) == i:
result = s + str(len_s + i)
break
i += 1
This code gives the result.
I used a few var, but at the end it shows the output you want:
def len_s(s):
s = s + '|'
b = len(s)
z = s + str(b)
length = len(z)
new_s = s + str(length)
new_len = len(new_s)
return s + str(new_len)
s = "A string"
print len_s(s)
Here's a direct equation for this (so it's not necessary to construct the string). If s is the string, then the length of the string including the length of the appended length will be:
L1 = len(s) + 1 + int(log10(len(s) + 1 + int(log10(len(s)))))
The idea here is that a direct calculation is only problematic when the appended length will push the length past a power of ten; that is, at 9, 98, 99, 997, 998, 999, 9996, etc. To work this through, 1 + int(log10(len(s))) is the number of digits in the length of s. If we add that to len(s), then 9->10, 98->100, 99->101, etc, but still 8->9, 97->99, etc, so we can push past the power of ten exactly as needed. That is, adding this produces a number with the correct number of digits after the addition. Then do the log again to find the length of that number and that's the answer.
To test this:
from math import log10
def find_length(s):
L1 = len(s) + 1 + int(log10(len(s) + 1 + int(log10(len(s)))))
return L1
# test, just looking at lengths around 10**n
for i in range(9):
for j in range(30):
L = abs(10**i - j + 10) + 1
s = "a"*L
x0 = find_length(s)
new0 = s+`x0`
if len(new0)!=x0:
print "error", len(s), x0, log10(len(s)), log10(x0)

TypeError when trying to perform multiplication on array of integers

This bit is fine just makes sense to put it in
digit = input("input a 5 digit number:")
if len(digit)==5:
digit = list(digit)
print(int(digit[2]))
print(int(digit[4]))
else:
print("error")
Here I am trying to multiply the 2nd and 4th digit by 2
new_digit1 = int(digit[0]*"%d" %1)
new_digit2 = int(digit[1]*"%d" %2)
new_digit3 = int(digit[2]*"%d" %1)
new_digit4 = int(digit[3]*"%d" %2)
new_digit5 = int(digit[4]*"%d" %1)
printable_digit = new_digit1 + new_digit2 + new_digit3 + new_digit4 + new_digit5
The error:
TypeError: can't multiply sequence by non-int of type 'str'
digits = raw_input("enter your 5 digit number") # raw input will keep it as a string
digs = list(digits)
This line should be
new_digit2 = int(digit[1]*"%d" %2)
should be
new_digit2 = int(digit[1])*2
* and % have the same precedence, regardless of what types they are used on. As such, digit[0]*"%d" is evaluated first, and the result used with % 1. You appear to be expecting "%d" % 1 to be evaluated first, with that used as the multiplier (or multiplicand, no one can seem to agree which is which) along with digit[0].
That is, digit[0] * "%d" % 1 is equivalent to (digit[0] * "%d") % 1, and you are trying to multiply two strings together.
You need to use parentheses to force the desired evaluation order.
digit[0] * ("%d" % 1)
(I'm ignoring the question of why you aren't just multiplying each digit by the integer directly. There's not much need for the % operator here.)

Categories