Python: Finding the length of a float with zeros at the end - python

I have several float values that have necessary zeros at the ends.
One number that I have is 0.0013790.
When finding the length of this, I get 8 when I should be getting 9, since the zero at the end is dropped. I can not use .format(), since some numbers are shorter than others and there is no concrete length that I want them set to. If I had a float that was seven digits long after the decimal and set the format to 8, I would get an extra zero which should NOT belong there.
I can not afford to have my program adding zeros through format when they are not always necessary, since some numbers will be shorter than others. How do I find the actual length of these numbers when a zero is at the end?
I can not make an if statement that checks if the number .endswith 0, because it never does. The zero is always dropped! I am already checking the length of the string of the float and still the zero is dropped! Many numbers will not end with zero, so I can not simply add one to the length found. Please help!
Numbers to test:
When inputting _, you should get _. If you can get the below to work along with some other numbers, please give me the solution. I've been racking at my brain for hours!! Thanks.
WANTED RESULTS: 0.12345 -> 7, 0.123450 -> 8, 0.1234500 -> 9.
UPDATE:
Thank you for your solutions, but the numbers are not inputs. I have them set to the eval() function, since I have roughly 1000 variables that need to be accessed dynamically from a websocket. Values are retrieved just fine, but if I am not mistaken, eval() defaults to float. Switching it from float to string has not done me much good, since I am guessing that eval() is always a float. Any solutions??

You need to store your values as strings if you want to track length independent of the value of the float.
Floating point values have no length, and trailing 0s do not affect the value so they produce identical floats. This means after it gets defined, there is no way to determine whether 0.12345 was defined using 0.12345 or 0.12345000000.
0.12345 is 0.123450 # True
0.12345 is 0.1234500 # True
len(0.12345) # TypeError: object of type 'float' has no len()
Everything works fine for the string representation of those floats:
"0.12345" is "0.123450" # False
"0.12345" is "0.1234500" # False
len("0.12345") # 7
Thus you should store these values as strings, and convert them to float when necessary.

If you first convert the input to a number, and then to a string, you'll lose any insignificant digits.
If you are asking the user to enter the value:
>>> foo = input('Enter the number here: ')
Enter the number here: 0.0013790
>>> len(foo)
9
If you are using Python 2, make sure you use raw_input and not input
As long as you don't cast the value to a float, you should get correct values for len().

Then we have to store the float as a string value. Following lines may be answer to the question where it is a default behaviour.
mynum = input('Enter your number: ')
print('Hello', mynum)
print(len(mynum))

Related

Convert Python Series of strings into float with 18 decimals

I have the following pandas Series:
my_series = ['150000000000000000000000', '45064744242514231410', '2618611848503168287542', '7673975728717793369']
Every number in the list has 18 decimal places (that's what dictates what number exactly it is, prior to seeing any formatting).
my_series[0], therefore, is 150,000.000000000000000000 (one hundred and fifty thousand).
my_series[1], therefore, is 45.064744242514231410 (fourty-five...).
And so on.
I basically want Python to recognize the strings and tunr them into the correct float for me to make calculations with thie Series later.
I don't need to print the correct formatted number, rather, have Pythoin recognize it's a 150,000 instead of a 1,500,000,000 and so on.
Example for my_series[2] of what the corrrect float would be:
2,618.61
My current code:
[float("{:.18f}".format(int(item) for item in my_series))]
Which yields me the following error:
TypeError: unsupported format string passed to generator.__format__
How do I format the strings in the Series according to my requirements above and get the correct float?
You can convert the string to float and then apply formatting.
my_series = ['150000000000000000000000', '45064744242514231410',
'2618611848503168287542', '7673975728717793369']
["{:,.2f}".format(float(item)/10**18) for item in my_series]
['150,000.00', '45.06', '2,618.61', '7.67']
Note that this may lose some precision when converting the string to float.
If this is a problem to you, then you may want to use either
Separate the integer part and decimal part and combine them when printing
Use Decimal class
After a few iterations, I think I understand what OP was going for, so I changed my example. OP does not seem to be worried about loss of precision and was getting value errors (probably due to invalid fields coming in as part of the Series). I've modified my sample to be close to how it would happen in Pandas by adding some deliberately fake inputs.
my_series = [
"not a number",
"",
"150000000000000000000000",
"45064744242514231410",
"2618611848503168287542",
"7673975728717793369",
]
def convert_to_float(number):
float_string = None
my_float = None
try:
float_string = f"{int(number[:-18])}.{number[-18:]}"
my_float = float(float_string)
except ValueError as e:
print(e)
return None
return my_float
numbers = list(map(convert_to_float, my_series))
for num in numbers:
if num:
print(f"{num :.18f}")

Convert a decimal number into a byte size of 8 bit array

x = 64
var_in_bin_format = bin(64)
print(var_in_bin_format)
#Output
#0b1000000
#Desired Output -- > should always be in 8 bit format
#0b01000000
def call_another_api(var_in_bin_format):
pass
In Python, I need to call an API that expects its parameter to be always in 8 bit format regardless of the value of the decimal number?
I am not that good in bit manipulation so I am thinking if there is something I can do here?
How can I do this? I cannot use the format() function as it will convert the value into a string representation and the API that I am calling will alert me that it is not in the correct format.
Even though you say that you can't use format() because it returns a string, I'm going to post this because that's also what bin() does. bin(x) is equivalent to format(x, '#b'). I'd guess that you haven't added the '#', which means you won't have '0b' leading the value.
The Python 3 documentation for bin() actually gives a pretty strong hint about how you might do this, using format instead.
If you know that the value passed will not be negative, you can use the format string '#010b':
format(x, '#010b')
Breaking this down:
'b' means that the number will be a string binary representation.
'10' means that the entire string will be 10 characters long, two for '0b' and 8 for the value.
'0' makes it pad with '0' instead of ' '.
'#' will add the '0b' prefix, as done by bin().
Note that this assumes that the number is an integer in the range [0, 255]. Integers outside this range will generate valid representations, but will not match the format expected, and may have a leading '-'. Objects of type float can not be converted with the 'b' format code. I assume that these are not problems, given what your intended output is, but it might be a good idea to add an explicit check to throw a ValueError if the value is less than 0 or greater than 255.
If you're in Python 3.6+, you could also use f-strings:
f'{x:#010b}'
Is is not possible to convert all decimal numbers to 8 bit. You can only convert numbers from 0 to 255 in 8 bits.

Python : Conversion of float to string keeping all digits of decimal place

I have a task to count the digits after decimal place.
For which I am using the below code :
str(string_name)[::-1].find('.')
But while converting float to string, it is removing the trailing zeroes :
my_string = 16.520440
print(str(my_string ))
output - '16.52044'
expected output - '16.520440'
Since that trailing zero is not a significant digit, there is no way you can do this within the given paradigm. Floats are stored by value, not by the visual representation of the original input. For instance:
my_string_1 = 16.52044
my_string_2 = 16.520440
my_string_3 = 16.5204400
my_string_4 = 016.5204400
All assign exactly the same value to the LHS variable: they have the same binary representation. Leading and trailing zeros do not, by definition, affect this value. There is no way to differentiate the original input from the stored value.
If you want some such effect, then you need to use some other form of original value that incorporates that information. For instance, you could add a second variable that denotes the quantity of significant decimal places -- which is the opposite of what you're trying to achieve -- or perhaps make the original input a string, from which you could derive that information.

How to compare specific items in a string python

E.g. in a given input the fourth digit must be one greater than the fifth digit
input = "5000-0000-0000"
if input[3] != input[5] + 1
return false
If you think about what input[3] and input[5] are, you will pretty quickly realize they are characters and not numbers that can be added or compared with mathematical operations (think about what would happen if you wrote input = "Andrew Francis").
You can see this by using print(type(input[3])).
Fortunately, if you have a string that contains only characters that make up a valid number, you can convert it to (for instance) an integer using the int() function. So, try print(type(int(input[3]))) and see what you get.

Avoid rounding float in python

I have rather unusual request, but I hope someone might be able to help.
I am appending floats as values to numpy array.
I would like to make sure that float does not get rounded when its decimal part ends in 0.
For example:
I would like float 31.30 to stay 31.30 in the array, but what I am experiencing now is that it gets set to 31.3.
The reason why I want to make sure float does not change is that later on I am splitting it to two integers(31.30 to 31 and 30) and it is of critical importance for me that both integers have the 'complete' values.
Is there any way to get around this? I tried with making these floats strings, but my problem is that I need to compare the arrays with these floats and numpy.array_equal() does not seem to work for arrays of strings...
Any help will be greatly appreciated,
Best wishes
Since 31.3 and 31.30 are exactly the same number, there is no way to distinguish them. But I guess you don't need to anyway. This seems more like a formatting issue. If you always expect two digits after the dot:
from math import floor
x = 31.3
whole_part = int(floor(x))
two_after_dot = int(floor(x*100))-whole_part*100
print(whole_part, two_after_dot)
Output:
31 30
If this actually isn't the case and the number of digits after the dot should vary while also keeping varying numbers of trailing zeros, then you cannot use numeric types. Use strings from the very beginning instead.
When I ran into a similar problem because of converting millisecond references to microseconds, I had to convert to a string and loop over the string adding the needed 0's until the length of the string was correct. Then when the value was converted back to integer, the calculations worked.
The data will be passed to strptime as as string
vals = vals.split('.') # a fractional part of the seconds
nofrag, frag = vals
length = len(frag)
# This converts the fractional string to microseconds, given unknown precision
if length > 6:
frag = frag(0:5)
else:
while length < 6:
frag = frag + '0'
length += 1
# strptime requires even seconds with microseconds added later
nofrag_dt = DT.datetime.strptime(nofrag, '%Y%m%d %H%M%S')
dt = nofrag_dt.replace(microsecond=int(frag))
return dt

Categories