I have a script that calls a function that takes a hexadecimal number for an argument. The argument needs to the 0x prefix. The data source is a database table and is stored as a string, so it is returned '0x77'. I am looking for a way to take the string from the database and use it as an argument in hex form with the 0x prefix.
This works:
addr = 0x77
value = class.function(addr)
The database entry has to be a string, as most of the other records do not have hexadecimal values in this column, but the values could be changed to make it easier, so instead of '0x77', it could be '119'.
Your class.function expects an integer which can be represented either by a decimal or a hexadecimal literal, so that these two calls are completely equivalent:
class.function(0x77)
class.function(119) # 0x77 == 119
Even print(0x77) will show 119 (because decimal is the default representation).
So, we should rather be talking about converting a string representation to integer. The string can be a hexadecimal representation, like '0x77', then parse it with the base parameter:
>>> int('0x77', 16)
119
or a decimal one, then parse it as int('119').
Still, storing integer whenever you deal with integers is better.
EDIT: as #gnibbler suggested, you can parse as int(x, 0), which handles both formats.
>>> hex(119)
'0x77'
#or:
>>> hex(int("119"))
'0x77'
This should work for you.
You can also get the hex representation of characters:
>>> hex(ord("a"))
'0x61'
I think you're saying that you read a string from the database and you want to convert it to an integer, if the string has the 0x prefix you can convert it like so:
>>> print int("0x77", 16)
119
If it doesnt:
>>> print int("119")
119
Related
I am using python 3.8.5, and trying to convert from an integer in the range (0,65535) to a pair of bytes. I am currently using the following code:
from struct import pack
input_integer = 2111
bytes_val = voltage.to_bytes(2,'little')
output_data = struct.pack('bb',bytes_val[1],bytes_val[0])
print(output_data)
This produces the following output:
b'\x08?'
This \x08 is 8 in hex, the most significant byte, and ? is 63 in ascii. So together, the numbers add up to 2111 (8*256+63=2111). What I can't figure out is why the least significant byte is coming out in ascii instead of hex? It's very strange to me that it's in a different format than the MSB right next to it. I want it in hex for the output data, and am trying to figure out how to achieve that.
I have also tried modifying the format string in the last line to the following:
output_data = struct.pack('cc',bytes_val[1],bytes_val[0])
which produces the following error:
struct.error: char format requires a bytes object of length 1
I checked the types at each step, and it looks like bytes_val is a bytearray of length 2, but when I take one of the individual elements, say bytes_val[1], it is an integer rather than a byte array.
Any ideas?
All your observations can be verified from the docs for the bytes class:
While bytes literals and representations are based on ASCII text, bytes objects actually behave like immutable sequences of integers
In Python strings any letters and punctuation are represented by themselves in ASCII, while any control codes by their hexadecimal value (0-31, 127). You can see this by printing ''.join(map(chr, range(128))). Bytes literals follow the same convention, except that individual byte elements are integer, i.e., output_data[0].
If you want to represent everything as hex
>>> output_data.hex()
'083f'
>>> bytes.fromhex('083f') # to recover
b'\x08?'
As of version 3.8 bytes.hex() now supports optional sep and bytes_per_sep parameters to insert separators between bytes in the hex output.
>>> b'abcdef'.hex(' ', 2)
'6162 6364 6566'
Let's assume that I get number as string or hex or int and I want to convert to integer. I'm looking for a more generic form.
for example,
if I write:
int('0x10',16) then int('0x10') will throw exception.
if I write:
int('10') then int('10',16) will throw exception.
Do I need to check type with instanceof ?
If the string represents a valid hex, it is prefixed by 0x. So, you could just check value.startswith('0x')
You need to specify the base (docs), when using int() on a hex value:
>>> _hex = hex(int("32"))
>>> _hex
'0x20'
>>> int(_hex, 0) # 0 means: Python automatically detects hex or decimal
32
I'm doing some calculations which give very small decimal numbers for example, 0.0000082
When I'm saving it in a variable, it changes into exponent form. I need the result as a string in the end. So, converting the result using str() is not possible because it keeps the e in the string.
I need the string to have exactly 8 decimal places. Is there any way to do this while keeping the 8 digit precision intact?
Another example: 5.8e-06 should be converted to '0.00000580' The trailing zero in the final string is not important.
I need the string to be used elsewhere. So, this shouldn't be done in the print() function.
The exponential notation is not an inherent property of the number (which is stored as a binary floating point value). It's just the default representation when converting the number to a string with str. You can specify your own formatting options if you convert the number to a string using the format function. Try something like this:
format(5.8e-06, '.8f')
The 8 in the format specifier tells it to use eight digits of precision, while the f requests it to be written as a plain decimal without exponential notation. You can read more about the format notations in the documentation.
Just another idea:
'{0:.7f}'.format(0.0000082)
you can try with :
import decimal
print(str(decimal.Decimal(5.8e-06))[:10])
>>> 0.00000580
print ("{:.6f}".format(1e-4))
will print out
0.000100
You could use print:
>>> number = 1e-08
>>> number
1e-08
>>>print("{:.12f}".format(float(number)))
0.000000010000
or You could convert number and store it in string:
>>> str1 = "{:.12f}".format(float(number))
>>> str1
'0.000000010000'
I have a function that accepts 'data' as a parameter. Being new to python I wasn't really sure that that was even a type.
I noticed when printing something of that type it would be
b'h'
if I encoded the letter h. Which dosen't make a ton of sense to me. Is there a way to define bits in python, such as 1 or 0. I guess b'h' must be in hex? Is there a way for me to simply define an eight bit string
bits1 = 10100000
You're conflating a number of unrelated things.
First of all, (in Python 3), quoted literals prefixed with b are of type bytes -- that means a string of raw byte values. Example:
x = b'abc'
print(type(x)) # will output `<class 'bytes'>`
This is in contrast to the str type, which is a (Unicode) string.
Integer literals can be expressed in binary using an 0b prefix, e.g.
y = 0b10100000
print(y) # Will output 160
For what I know, 'data' is not a type. Your function (probably) accepts anything you pass to it, regardless of its type.
Now, b'h' means "the number (int) whose binary sequence maps to the char ´h´", this is not hexadecimal, but a number with possibly 8 bits (1 byte, which is the standard size for int and char).
The ASCII code for ´h´ is 104 (decimal), written in binary that would be b'\b01101000', or in hexa b'\x68'.
So, here is the answer I think you are looking for: if you want to code an 8-bit int from its binary representation just type b'\b01101000' (for 104). I would recommend to use hexa instead, to make it more compact and readable. In hexa, every four bits make a symbol from 0 to f, and the symbols can be concatenated every four bits to form a larger number. So the bit sequence 01101000 is written b'\b0110\b1000' or b'\x6\x8', which can be written as b'\x68'. The preceding b, before the quote marks tells python to interpret the string as a binary sequence expressed in the base defined by \b or \x (or \d for decimal), instead of using escape characters.
So, I've been banging my head against the wall for too long on what seems like it should be an easy data conversion. I am writing in python and passing to another module a hex value that is converted with a wrapper to c type uint_64t. the problem is I am getting this hex value via the python library argparse. When it takes in this value, for example lets use the value 0x3f, it saves it as a string. If I try to cast this as an int it throws the error:
"ValueError: invalid literal for int() with base 10: '0x3f'"
If I create a variable hex = 0x3f however, when I print it out, it gives me the appropriate integer value. (which is great since I'm creating a uint) I am just confused how to make the conversion from string to int if a cast doesn't work. I have seen plenty of examples on turning this string into a hex value by letter (in other words take each individual character of the ascii string '0x3f' and give it a hex value) but I haven't been able to find an example of the situation I am looking for. Apologies if I'm bringing up something that has been answered time and again.
Try specifying that the int is in base 16:
>>> int("0x3f", 16)
63
You could also use ast.literal_eval, which should be able to read any string that could be used as an integer literal. You don't even have to specify a base for this one, as long as the 0x prefix is present.
>>> import ast
>>> #hexadecimal
>>> ast.literal_eval("0x3f")
63
>>> #binary
>>> ast.literal_eval("0b01010")
10
>>> #octal
>>> ast.literal_eval("0712")
458
>>> #decimal
>>> ast.literal_eval("42")
42
int takes an optional second argument, which is the numerical base to use for conversion. The default is 10 (decimal conversion) but you can change it to 16 (for hex) or 0 (for automatic conversion based on prefix):
>>> int('0b1010', 0)
10
>>> int('0x3f', 0)
63
>>> int('0o777', 0)
511
>>> int('1234', 0)
1234