Remove decimal number from the function eval() [duplicate] - python

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

Related

How to print whole number without zeros after decimal point?

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}.”)

In Python, how can I get a whole number without decimals from math.sqrt?

import math
a = math.sqrt(25)
print(a)
My output is 5.0, how can I get a 5 (whole number) instead?
You have to check and explicitly convert to integer:
if x == (y := int(x)):
x = y
Or, without the assignment operator:
if x == int(x):
x = int(x)
As of python 3.8, you can use math.isqrt:
math.isqrt(25)
Keep in mind that this will always return an integer, even if the input is not a perfect square.
In a reduced manner, you can use a 1 line if operator to assign an integer value to the result of sqrt if both integer and decimal values are the same:
import math
a = math.sqrt(25)
a = int(a) if int(a)==a else a
print(a)
It depends a little on what exact behavior you want: do you want to just print the number without the decimal, or do you want to round a number to an integer?
For the print statement, Python tries to convert whatever is passed to it to a String in order to print it, and by default it gives floating point numbers decimal places. To stop that, we can use string formatting:
print("{:.0f}".format(a))
What this is doing is making a string (the double quotes "") that contains a special format marker (the curly braces {}). Inside the format marker is the code for the desired behavior (0 decimal places on a floating point number). Then we call the .format method of the string and pass the value (a) we want to be used inside the special format marker.
This looks somewhat arcane and ugly, but is the safest method to print what you want because it does not change 'a' and is easily customizable to other printing behaviors.
For rounding a number and converting it to an int, you can either use int() or round(): both will take in a float and output an integer that will print cleanly (and be an integer for future computation). There is no requirement for the thing being converted to actually be an integer but there is different behavior for the two functions: int returns the value of the first digit of a number, while round returns the rounded value (IE round(1.9) -> 2, int(1.9) -> 1, etc).

Why doesn't Python include number of digits I specify after the decimal point when rounding?

For example,
a = 5 * 6.2
print (round(a, 2)
The output is 31.0. I would have expected 31.00.
b = 2.3 * 3.2
print (round(b, 3))
The output is 7.36. I would have expected 7.360.
You are confusing rounding with formatting. Rounding produces a new float object with the rounded value, which is still going to print the same way as any other float:
>>> print(31.00)
31.0
Use the format() function if you need to produce a string with a specific number of decimals:
>>> print(format(31.0, '.2f'))
31.00
See the Format Specification Mini-Language section for what options you have available.
If the value is part of a larger string, you can use the str.format() method to embed values into a string template, using the same formatting specifications:
>>> a = 5 * 6.2
>>> print('The value of "a" is {:.2f}'.format(a))
Python always prints at least one digit after the decimal point so you can tell the difference between integers and floats.
The round() function merely rounds the number to the specified number of decimal places. It does not control how it is printed. 7.36 and 7.360 are the same number, so the shorter is printed.
To control the printing, you can use formatting. For example:
print(".3f" % b)
Python does round to 3 decimal places. It is the printing that cuts additional zeros. Try something like print("%.3f" % number)

Float converted to 2.dp reverts to original number of decimal places when inserted into a string

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

Format a number containing a decimal point with leading zeroes

I want to format a number with a decimal point in it with leading zeros.
This
>>> '3.3'.zfill(5)
003.3
considers all the digits and even the decimal point. Is there a function in python that considers only the whole part?
I only need to format simple numbers with no more than five decimal places. Also, using %5f seems to consider trailing instead of leading zeros.
Is that what you look for?
>>> "%07.1f" % 2.11
'00002.1'
So according to your comment, I can come up with this one (although not as elegant anymore):
>>> fmt = lambda x : "%04d" % x + str(x%1)[1:]
>>> fmt(3.1)
0003.1
>>> fmt(3.158)
0003.158
I like the new style of formatting.
loop = 2
pause = 2
print 'Begin Loop {0}, {1:06.2f} Seconds Pause'.format(loop, pause)
>>>Begin Loop 2, 0002.1 Seconds Pause
In {1:06.2f}:
1 is the place holder for variable pause
0 indicates to pad with leading zeros
6 total number of characters including the decimal point
2 the precision
f converts integers to floats
print('{0:07.3f}'.format(12.34))
This will have total 7 characters including 3 decimal points, ie. "012.340"
Like this?
>>> '%#05.1f' % 3.3
'003.3'
Starting with a string as your example does, you could write a small function such as this to do what you want:
def zpad(val, n):
bits = val.split('.')
return "%s.%s" % (bits[0].zfill(n), bits[1])
>>> zpad('3.3', 5)
'00003.3'
With Python 3.6+ you can use the fstring method:
f'{3.3:.0f}'[-5:]
>>> '3'
f'{30000.3:.0f}'[-5:]
>>> '30000'
This method will eliminate the fractional component (consider only the whole part) and return up to 5 digits. Two caveats: First, if the whole part is larger than 5 digits, the most significant digits beyond 5 will be removed.
Second, if the fractional component is greater than 0.5, the function will round up.
f'{300000.51:.0f}'[-5:]
>>>'00001'

Categories

Resources