I'm trying to print a whole number (such as 39 for example) in the following format: 39.
It must not be a str type object like '39.' for example, but a number
e. g. n = 39.0 should be printed like 39.
n = 39.0
#magic stuff with output
39.
I tried using :.nf methods (:.0f apparently -- didn't work), print(float(39.)) or just print(39.)
In the first case, it looks like 39, in the second and third 39.0
I also tried float(str(39) + '.') and obviously it didn't work
Sorry, if it's a stupid question, I've been trying to solve it for several hours already, still can't find any information.
From Format Specification Mini-Language (emphasis mine):
The '#' option causes the “alternate form” to be used for the conversion. The alternate form is defined differently for different types. This option is only valid for integer, float and complex types. For integers, when binary, octal, or hexadecimal output is used, this option adds the respective prefix '0b', '0o', '0x', or '0X' to the output value. For float and complex the alternate form causes the result of the conversion to always contain a decimal-point character, even if no digits follow it. Normally, a decimal-point character appears in the result of these conversions only if a digit follows it. In addition, for 'g' and 'G' conversions, trailing zeros are not removed from the result.
>>> n=39.0
>>> print(f'{n:#.0f}')
39.
print(int(n))
or u can try:
n = n // 1
print(f”{n}.”)
Related
This is a hackerrank practice problem https://www.hackerrank.com/challenges/python-string-formatting/problem . It is not actually a difficult problem, but one of the solutions posted in the discussion is confusing. I am adding their function for doing the same below:
def print_formatted(number):
p = len(f"{number:b}")
for i in range(1,number+1): print(f"{i: >{p}} {i: >{p}o} {i: >{p}X} {i: >{p}b}")
Even though b is not defined it is not throwing an error. If I just do 5:6 in python, it throws an error. But if I do print(f"{5:6}"), it prints adds 6 spaces before 5 and prints it. What exactly is happening here and what are the common use cases for this?
What exactly is happening in the print statement? What does all the o, X nd b do? Why is there a {} inside one active {} and what does it do?
Format Specification Mini-Language
“Format specifications” are used within replacement fields contained
within a format string to define how individual values are presented
(see Format String Syntax and Formatted string literals). They can
also be passed directly to the built-in format() function. Each
formattable type may define how the format specification is to be
interpreted.
The available integer presentation types are:
Type
Meaning
'b'
Binary format. Outputs the number in base 2.
'c'
Character. Converts the integer to the corresponding unicode character before printing.
'd'
Decimal Integer. Outputs the number in base 10.
'o'
Octal format. Outputs the number in base 8.
'x'
Hex format. Outputs the number in base 16, using lower-case letters for the digits above 9.
'X'
Hex format. Outputs the number in base 16, using upper-case letters for the digits above 9. In case '#' is specified, the prefix '0x' will be upper-cased to '0X' as well.
'n'
Number. This is the same as 'd', except that it uses the current locale setting to insert the appropriate number separator characters.
None
The same as 'd'.
Source
Unfortunately the printing instruction of a code was written without an end-of-the-line character and one every 26 numbers consists of two numbers joined together. The following is a code that shows an example of such behaviour; at the end there is a fragment of the original database.
import numpy as np
for _ in range(2):
A=np.random.rand()+np.random.randint(0,100)
B=np.random.rand()+np.random.randint(0,100)
C=np.random.rand()+np.random.randint(0,100)
D=np.random.rand()+np.random.randint(0,100)
with open('file.txt','a') as f:
f.write(f'{A},{B},{C},{D}')
And thus the output example file looks very similar to what follows:
40.63358599010553,53.86722741700399,21.800795158561158,13.95828176311762557.217562728494684,2.626308403991772,4.840593988487278,32.401778122213486
With the issue being that there are two numbers 'printed together', in the example they were as follows:
13.95828176311762557.217562728494684
So you cannot know if they should be
13.958281763117625, 57.217562728494684
or
13.9582817631176255, 7.217562728494684
Please understand that in this case they are only two options, but the problem that I want to address considers 'unbounded numbers' which are type Python's "float" (where 'unbounded' means in a range we don't know e.g. in the range +- 1E4)
Can the original numbers be reconstructed based on "some" python internal behavior I'm missing?
Actual data with periodicity 27 (i.e. the 26th number consists of 2 joined together):
0.9221878978925224, 0.9331311610066017,0.8600582424784715,0.8754578588852764,0.8738648974725404, 0.8897837559800233,0.6773502027673041,0.736325377603136,0.7956454122424133, 0.8083168444596229,0.7089031184165164, 0.7475306242508357,0.9702361286847581, 0.9900689384633811,0.7453878225174624, 0.7749000030576826,0.7743879170108678, 0.8032590543649807,0.002434,0.003673,0.004194,0.327903,11.357262,13.782266,20.14374,31.828905,33.9260060.9215201173775437, 0.9349343132442707,0.8605282244327555,0.8741626682026793,0.8742163597524663, 0.8874673376386358,0.7109322043854609,0.7376362393985332,0.796158275345
To expand my comment into an actual answer:
We do have some information - An IEEE-754 standard float only has 32 bits of precision, some of which is taken up by the mantissa (not all numbers can be represented by a float). For datasets like yours, they're brushing up against the edge of that precision.
We can make that work for us - we just need to test whether the number can, in fact, be represented by a float, at each possible split point. We can abuse strings for this, by testing num_str == str(float(num_str)) (i.e. a string remains the same after being converted to a float and back to a string)
If your number is able to be represented exactly by the IEEE float standard, then the before and after will be equal
If the number cannot be represented exactly by the IEEE float standard, it will be coerced into the nearest number that the float can represent. Obviously, if we then convert this back to a string, will not be identical to the original.
Here's a snippet, for example, that you can play around with
def parse_number(s: str) -> List[float]:
if s.count('.') == 2:
first_decimal = s.index('.')
second_decimal = s[first_decimal + 1:].index('.') + first_decimal + 1
split_idx = second_decimal - 1
for i in range(second_decimal - 1, first_decimal + 1, -1):
a, b = s[:split_idx], s[split_idx:]
if str(float(a)) == a and str(float(b)) == b:
return [float(a), float(b)]
# default to returning as large an a as possible
return [float(s[:second_decimal - 1]), float(s[second_decimal - 1:])]
else:
return [float(s)]
parse_number('33.9260060.9215201173775437')
# [33.926006, 0.9215201173775437]
# this is the only possible combination that actually works for this particular input
Obviously this isn't foolproof, and for some numbers there may not be enough information to differentiate the first number from the second. Additionally, for this to work, the tool that generated your data needs to have worked with IEEE standards-compliant floats (which does appear to be the case in this example, but may not be if the results were generated using a class like Decimal (python) or BigDecimal (java) or something else).
Some inputs might also have multiple possibilities. In the above snippet I've biased it to take the longest possible [first number], but you could modify it to go in the opposite order and instead take the shortest possible [first number].
Yes, you have one available weapon: you're using the default precision to display the numbers. In the example you cite, there are 15 digits after the decimal point, making it easy to reconstruct the original numbers.
Let's take a simple case, where you have only 3 digits after the decimal point. It's trivial to separate
13.95857.217
The formatting requires a maximum of 2 digits before the decimal point, and three after.
Any case that has five digits between the points, is trivial to split.
13.958 57.217
However, you run into the "trailing zero" problem in some cases. If you see, instead
13.9557.217
This could be either
13.950 57.217
or
13.955 07.217
Your data do not contain enough information to differentiate the two cases.
I want my Python (2.4.3) output numbers to have a certain format. Specifically, if the number is a terminating decimal with <= 6 significant digits, show it all. However, if it has > 6 significant digits, then output only 6 significant digits.
"A" shows how Python is writing the floats. "B" shows how I want them written. How can I make Python format my numbers in that way?
A:
10188469102.605597
5.5657188485
3.539
22.1522612479
0
15.9638450858
0.284024
7.58096703786
24.3469152383
B:
1.01885e+10
5.56572
3.539
22.1523
0
15.9638
0.284024
7.58097
24.3469
You'll want the g modifier for format that drops insignificant zeroes;
>>> "{0:.6g}".format(5.5657188485)
'5.56572'
>>> "{0:.6g}".format(3.539)
'3.539'
Sorry, my update also includes the fact that I am restricted to using
Python 2.4.3, which does not have format() function.
The format specifiers work even without the .format() function:
>>> for i in a:
... print '%.6g' % (i,)
...
1.01885e+10
5.56572
3.539
22.1523
0
15.9638
0.284024
7.58097
24.3469
There is a way to retain trailing zeros so that it consistently shows the number of significant digits. Not exactly what OP wanted, but probably useful to many.
a = [10188469102.605597,5.5657188485,3.539,22.1522612479,0,15.9638450858,0.284024,7.58096703786,24.3469152383]
for i in a:
print("{:#.6g}".format(i))
Output
1.01885e+10
5.56572
3.53900
22.1523
0.00000
15.9638
0.284024
7.58097
24.3469
Note that this will only work with the format function and not with % operator.
According to the docs:
The '#' option causes the “alternate form” to be used for the conversion. The alternate form is defined differently for different types. This option is only valid for integer, float, complex and Decimal types.
'g': General format ... insignificant trailing zeros are removed from the significand, and the decimal point is also removed if there are no remaining digits following it, unless the '#' option is used.
try this way
a=[10188469102.605597,5.5657188485,3.539,22.1522612479,0,15.9638450858,0.284024,7.58096703786,24.3469152383]
for i in a:
if i >100:
print '{:.6e}'.format(i)
else:
print '{:.6f}'.format(i)
for lower version of python
for i in a:
if i >100:
print '%6e'%i
else:
print '%6f'%i
output
1.018847e+10
5.565719
3.539000
22.152261
0.000000
15.963845
0.284024
7.580967
24.346915
I have created the following snippet of code and I am trying to convert my 5 dp DNumber to a 2 dp one and insert this into a string. However which ever method I try to use, always seems to revert the DNumber back to the original number of decimal places (5)
Code snippet below:
if key == (1, 1):
DNumber = '{r[csvnum]}'.format(r=row)
# returns 7.65321
DNumber = """%.2f""" % (float(DNumber))
# returns 7.65
Check2 = False
if DNumber:
if DNumber <= float(8):
Check2 = True
if Check2:
print DNumber
# returns 7.65
string = 'test {r[csvhello]} TESTHERE test'.format(r=row).replace("TESTHERE", str("""%.2f""" % (float(gtpe))))
# returns: test Hello 7.65321 test
string = 'test {r[csvhello]} TESTHERE test'.format(r=row).replace("TESTHERE", str(DNumber))
# returns: test Hello 7.65321 test
What I hoped it would return: test Hello 7.65 test
Any Ideas or suggestion on alternative methods to try?
It seems like you were hoping that converting the float to a 2-decimal-place string and then back to a float would give you a 2-decimal-place float.
The first problem is that your code doesn't actually do that anywhere. If you'd done that, you would get something very close to 7.65, not 7.65321.
But the bigger problem is that what you're trying to do doesn't make any sense. A float always has 53 binary digits, no matter what. If you round it to two decimal digits (no matter how you do it, including by converting to string and back), what you actually get is a float rounded to two decimal digits and then rounded to 53 binary digits. The closest float to 7.65 is not exactly 7.65, but 7.650000000000000355271368.* So, that's what you'd end up with. And there's no way around that; it's inherent to the way float is stored.
However, there is a different type you can use for this: decimal.Decimal. For example:
>>> f = 7.65321
>>> s = '%.2f' % f
>>> d = decimal.Decimal(s)
>>> f, s, d
(7.65321, '7.65', Decimal('7.65'))
Or, of course, you could just pass around a string instead of a float (as you're accidentally doing in your code already), or you could remember to use the .2f format every time you want to output it.
As a side note, since your DNumber ends up as a string, this line is not doing anything useful:
if DNumber <= 8:
In Python 2.x, comparing two values of different types gives you a consistent but arbitrary and meaningless answer. With CPython 2.x, it will always be False.** In a different Python 2.x implementation, it might be different. In Python 3.x, it raises a TypeError.
And changing it to this doesn't help in any way:
if DNumber <= float(8):
Now, instead of comparing a str to an int, you're comparing a str to a float. This is exactly as meaningless, and follows the exact same rules. (Also, float(8) means the same thing as 8.0, but less readable and potentially slower.)
For that matter, this:
if DNumber:
… is always going to be true. For a number, if foo checks whether it's non-zero. That's a bad idea for float values (you should check whether it's within some absolute or relative error range of 0). But again, you don't have a float value; you have a str. And for strings, if foo checks whether the string is non-empty. So, even if you started off with 0, your string "0.00" is going to be true.
* I'm assuming here that you're using CPython, on a platform that uses IEEE-754 double for its C double type, and that all those extra conversions back and forth between string and float aren't introducing any additional errors.
** The rule is, slightly simplified: If you compare two numbers, they're converted to a type that can hold them both; otherwise, if either value is None it's smaller; otherwise, if either value is a number, it's smaller; otherwise, whichever one's type has an alphabetically earlier name is smaller.
I think you're trying to do the following - combine the formatting with the getter:
>>> a = 123.456789
>>> row = {'csvnum': a}
>>> print 'test {r[csvnum]:.2f} hello'.format(r=row)
test 123.46 hello
If your number is a 7 followed by five digits, you might want to try:
print "%r" % float(str(x)[:4])
where x is the float in question.
Example:
>>>x = 1.11111
>>>print "%r" % float(str(x)[:4])
>>>1.11
I have a string variable:
str1 = '0000120000210000'
I want to convert the string into an integer without losing the first 4 zero characters. In other words, I want the integer variable to also store the first 4 zero digits as part of the integer.
I tried the int() function, but I'm not able to retain the first four digits.
You can use two integers, one to store the width of the number, and the other to store the number itself:
kw = len(s)
k = int(s)
To put the number back together in a string, use format:
print '{:0{width}}'.format(k, width=kw) # prints 0000120000210000
But, in general, you should not store identifiers (such as credit card numbers, student IDs, etc.) as integers, even if they appear to be. Numbers in these contexts should only be used if you need to do arithmetic, and you don't usually do arithmetic with identifiers.
What you want simply cannot be done.. Integer value does not store the leading zero's, because there can be any number of them. So, it can't be said how many to store.
But if you want to print it like that, that can be done by formatting output.
EDIT: -
Added #TimPietzcker's comment from OP to make complete answer: -
You should never store a number as an integer unless you're planning on doing arithmetic with it. In all other cases, they should be stored as strings