randint with leading zero's - python

I want to generate numbers from 00000 to 99999.
with
number=randint(0,99999)
I only generate values without leading zero's, of course, a 23 instead of a 00023.
Is there a trick to generate always 5 digit-values in the sense of %05d or do I really need to play a python-string-trick to fill the missing 0s at front in case len() < 5?
Thanks for reading and helping,
B

You will have to do a python-string-trick since an integer, per se, does not have leading zeroes
number="%05d" % randint(0,99999)

The numbers generated by randint are integers. Integers are integers and will be printed without leading zeroes.
If you want a string representation, which can have leading zeroes, try:
str(randint(0, 99999)).rjust(5, "0")

Alternatively, str(randint(0, 99999)).zfill(5), which provides slightly better performance than string formatting (20%) and str.rjust (1%).

randint generates integers. Those are simple numbers without any inherent visual representation. The leading zeros would only be visible if you create strings from those numbers (and thus another representation).
Thus, you you have to use a strung function to have leading zeros (and have to deal with those strings later on). E.g. it's not possible to do any calculations afterwards. To create these strings you can do something like
number = "%05d" % random.randint(0,99999)
The gist of all that is that an integer is not the same as a string, even if they look similar.
>>> '12345' == 12345
False

For python, you're generating a bunch of numbers, only when you print it / display it is it converted to string and thus, it can have padding.
You can as well store your number as a formatted string:
number="%05d" % random.randint(0,9999)

Related

0's in the beginning are being skipped & I'm not sure how to fix it

The output value is not including the 0's in the beginning, can someone help me fix the problem?
def bitwiseOR(P, Q):
return bin(P | Q)
bitwiseOR(0b01010111, 0b00111000)
OUTPUT: '0b1111111'
The leading zeroes are just for representation, so you can utilize Format Specification Mini-Language to display them as you wish:
Format string:
# Includes 0b prefix
0{length} Pad leading zeroes so total length is length
def bitwiseOR(P, Q, length=10):
return format(P | Q, f'#0{length}b')
x = bitwiseOR(0b01010111, 0b00111000)
# 0b01111111
print(x)
Leading zeros are a property of the string you produce, not the number. So, for example, if you're looking for a way to make the following two calls produce different results, that's not possible:1
bitwiseOR(0b01010111, 0b00111000)
bitwiseOR( 0b1010111, 0b111000)
However, if you can provide the number of digits separately, then you can do this using the format() function. It accepts a second argument which lets you customize how the number is printed out using the format spec. Based on that spec, you can print a number padded with zeros to a given width like this:
>>> format(127, '#010b')
'0b01111111'
Here the code consists of four pieces:
# means apply the 0b prefix at the beginning
0 means pad with leading zeros
10 means the total length of the resulting string should be at least 10 characters
b means to print the number in binary
You can tweak the format code to produce your desired string length, or even take the length from a variable.
1Well... technically there is a way to make Python re-read its own source code and possibly produce different results that way, but that's not useful in any real program, it's only useful if you want to learn something about how the Python interpreter works.

Why is this random generator sometimes returning 3 digits instead of 4?

if choice == '1':
print('Your card has been created')
card = create_card()
print(f'Your card number:\n{card}')
pin = int(''.join(f'{random.randint(0, 9)}' for _ in range(4)))
print(f'Your card PIN:\n{pin}\n')
cards.append([card, pin])
Please can someone explain why the above code sometimes generates a 3-digit number as opposed to a 4-digit number? For example:
Others have explained why you sometimes end up with three-digit (or even two- or one-digit) results. You could view this as a formatting problem -- printing a number with leading zeroes to a specified width. Python does have features supporting that.
But I urge you to instead recognize that the problem is really that your data isn't actually a number in the first place. Rather, it is a string of digits, all of which are always significant. The easiest and best thing to do, then, is to simply keep it as a string instead of converting it to a number.
Your random generator is not returning four-digit numbers sometimes since it is putting a zero as the first digit. Numbers like 0322 are created by the random generator and it is being converted to 322. This generator can also make two-digit and one-digit numbers because of the zeros in front. If you want four-digit numbers only use pin = random.randint(1000, 9999). If you want numbers with leading zeros, use pin = ''.join(f'{random.randint(0, 1)}' for _ in range(4)). This keeps the leading zeros. Keeping the pin as a string stops the leading zeros from being removed.
In your logic, it's possible to generate a string that starts with 0. If you pass a leading 0 numeric string to int(), that leading 0 is ignored:
print(int("0999"))
Output
999
To fix this, you could just change the range start value.
pin = int(''.join(f'{random.randint(1, 9)}' for _ in range(4)))
Edit: To prove this to yourself, print both the generated string and the result of the int() function, like below.
for i in range(100):
st = ''.join(f'{random.randint(0, 9)}' for _ in range(4))
print(st, int(st))

How do I get hex() to print the full hex value in Python?

Say I have 2 hex values that were taken in from keyboard input.
E.g. val1 = 0x000000 and val2 = 0xFF0000
and I do,
print(hex(val1))
print(hex(val2))
I get the right output for val2 but val1 is just 0x0, how do I get it to print the whole value?
By whole value, I mean, if the inputted value is 0x000000, I want to output the value as 0x000000 and not 0x0.
Use the format() built-in function to show the hex representation to the expected level of precision:
>>> format(53, '08x')
'00000035'
>>> format(1234567, '08x')
'0012d687'
The format code 08x means "eight lowercase hex digits padded with leading zeros".
You can pad the hex value to the specified number of digits by using the ljust method.
Whenever the string is less than the specified width, it'll append the specified filler character to extend it.
In your example example, hex(0x0).ljust(8, '0') == "0x000000".
Strings that are already long enough are preserved so that 0xFF0000 will still work.
print(hex(0x000000).ljust(8, '0')) # Prints 0x000000
print(hex(0xFF0000).ljust(8, '0')) # Prints 0xFF0000
A couple of important things to note that have bitten me in the past:
Make sure your width includes the length of the leading "0x"
This is because the ljust function operator operates on raw text and doesn't realize it's a hex string
If you give a width value shorter than you need, the strings won't be filled up enough and will have different lengths.
In other words len(hex(0xFF0000).ljust(4, '0')) != len(hex(0xFF0000).ljust(4, '0')) because you need a length of 8 characters to fit both cases
You say the user typed this input in on the keyboard. That means you already started with the strings you want, but you parsed integers out of the input and threw away the strings.
Don't do that. Keep the strings. Parse integers too if you need to do math, but keep the strings. Then you can just do
print(original_input)
without having to go through a reconstruction process and guess at how many leading zeros were originally input.

How do I preserve leading zeros in Python integers for string formatting

I have what I believe to be a simple question. I have the following code and the output is not what I expect:
import socket
import time
r=031508.78
h=373309.9
z=0
mes='"TSRA %s %s %s\r\n"'%(r,h,z)
print mes
My problem is that r prints as '31508.78' and I want '031508.78'. How I get preserve the leading zero?
The 0 in front of the number is not important for python, because numbers have no leading 0s. You can use:
print '%09.2f'%r
I prefer the new string format mini language. I find it more intuitive.
r = 31508.78
h = 373309.9
z = 0
print '"TSRA {0: 011.3f} {1: 011.3f} {2}"\r\n'.format(r, h, z)
print '{0: 011.3f}\n{1: 011.3f}\n{2: 011.3f}'.format(r, h, z)
{0: 011.3f} 0: indicates the first item (r). 011 tells the formatter that there will be 11 characters including the decimal point and a place holder for a negative sign. By placing a 0 in front the formatter will pad the space with leading zeros. Finally, .3f indicates the precision and a fixed number of places after the decimal point.
Yields:
"TSRA 031508.780 373309.900 0"
031508.780
373309.900
000000.000
I don't think there is any way to store a number with a leading zero in python.
This leaves you with two ways:
1) Make r a string i.e. r="031408.78"
I think this is the best method for you as you can do all the arithmetic you want to do (using the implicit typecasting of python) and see the number appended with a 0 wherever you use it.
2) If you simply want to print the number with leading zeros consider using this
print "%09.2f' % r #for this you need the length of the number
For Python, there is no difference in the following things:
31508.78
031508.78
0000000031508.78
31508.7800000000000
0000000000000031508.7800000000000
Those are all valid representations of the exact same number, which is canonically represented by 31508.78, which is essentially just a convention. Different representations are possible too, and actually, the number is represented in a way that’s described by the IEEE-754 standard.
So, when you want that leading zero, you have to tell Python explicitely to put it there because it simply doesn’t know about it. You just used one of many valid representations to specify that one number which default string representation does not include leading zeroes.
The best way to do this is using string formatting, which comes in two flavors. The old style flavor, using the % operator, and the newer str.format function:
>>> '%09.2f' % 31508.78
'031508.78'
>>> '{:09.2f}'.format(31508.78)
'031508.78'
Or, if you don’t actually want a number, you could also just specify the number as a string to begin with, which of course keeps the leading zero.

How do I convert a padded string to an integer while preserving padding?

I followed the great example at Python: Nicest way to pad zeroes to string (4)
but now I need to turn that padded string to a padded integer.
I tried:
list_padded=['0001101', '1100101', '0011011', '0011011', '1101111',
'0000001', '1110111', 1101111', '0111001', '0011011',
'0011001'] # My padded sting list.
int_list=[int(x) for x in list_padded] # convert the string to an INT
But what I get is a list of integers sans the padding.
Appreciate any direction or suggestions.
Many thanks,
Jack
Edit: After learning the revelation that integers don't get padded, I'm thinking a little differently, however it would probably be a good idea to explain more:
I'm working through a basic encryption exercise in a book. It has given me a list of pseduocode to work through - get cipher string 1-127 and a message, convert both to binary, strip off the 0b, and pad with zeroes. However it wants me to do the rest WITHOUT XOR! I've gotten that far one line at a time, but now comes this (where the problem begins):
Perform manual XOR operation & append binary 7-bit result to encrypted string
Convert each binary bit of message character and key to an integer
Perform XOR operation on these two bits
Convert literal True and False to binary bit & append to output
I've love to use the XOR operation but I'm afraid doing so I'm not going to learn what I need to.
-J
Applying idea of padding to integers is meaningless. If you want to print/represent them you need strings, integers just don't have padding.
Integers don't have a concept of padding, but if you want then you can store both the value and the original length instead of just the value:
int_list = [(int(x), len(x)) for x in list_padded]
Then if you want to reconstruct the original data you have enough information to do so. You may even want to make a custom class to store both these fields instead of using a tuple.
Leading zeros is just for data representation:
"{0:b}".format(4).zfill(8)
You can change XOR with other bit-wise operations:
def xor(x, y):
return (~x & y) | (~y & x)
def bool_xor(x, y):
return ((not x) and y) or ((not y) and x)
Actually, you can express all bitwise operations with just one logical operation:
http://en.wikipedia.org/wiki/Functional_completeness
Since the INT type is a number it will be stored without leading zeros. Why would you want to store 675 as 00675? That's meaningless in the realm of integers. I would suggest storing the integers as integers and then only apply the padding when you access them and print them out (or whatever you are doing with them)

Categories