0

Using Python 2.7 on OSX, the output is different from x, wondering if there is a way to control Python double/float more precision?

x=0.123456789123456789

print x # output 0.123456789123

Update 1,

Weird output when using Decimal,

x=0.123456789123456789
y=decimal.Decimal(x)
print x," and ", y # output 0.123456789123  and  0.1234567891234567837965840908509562723338603973388671875

regards, Lin

Lin Ma
  • 9,739
  • 32
  • 105
  • 175
  • 3
    use the `Decimal` library: https://docs.python.org/2/library/decimal.html – juanpa.arrivillaga Jun 23 '16 at 22:26
  • 1
    You may find this helpful: http://stackoverflow.com/questions/8885663/how-to-format-a-floating-number-to-fixed-width-in-python – Moses Koledoye Jun 23 '16 at 22:27
  • 2
    Do you want more precision in the *output* shown (e.g., through `print`), or more precision in your actual *calculation*? –  Jun 23 '16 at 22:58
  • 2
    In "Update 1", you are using Decimal wrong. Remember to use a **string** not a **float** when you are creating the Decimal. Once you have a float, the precision is lost and you can't get it back. Correct code is `x='0.123456789123456789'` (notice the quotes). This was explained by @dmitryro below. – Dietrich Epp Jun 23 '16 at 23:21
  • @DietrichEpp, thanks and vote up, and you mean on this original line, `x=0.123456789123456789`, the precision is lost? – Lin Ma Jun 23 '16 at 23:22
  • 1
    Yes, the precision is lost already. Just by writing `0.123456789123456789`, the precision is gone even before you assign it to `x`. – Dietrich Epp Jun 23 '16 at 23:24
  • @DietrichEpp, nice catch. So, `Decimal` could only be used with string literal? – Lin Ma Jun 23 '16 at 23:32
  • 1
    You can use it however you want. You can use it with float, int, or string. Just be aware of the limitations of each. Decimal can't get back information that was already lost. (Minor note, Decimal just gets an ordinary string, the distinction between "string" and "string literal" is gone by that point.) – Dietrich Epp Jun 24 '16 at 00:23
  • @DietrichEpp, vote up and I tried to use `decimal.Decimal` on a Hadoop Python UDF and it said to use Decimal, it has to be converted to `str` first. Does it mean Hadoop Python (jython) is different from standard Python 2.7 implementation? – Lin Ma Jun 24 '16 at 06:27
  • @DietrichEpp, I tried and use standard Python 2.7 has no issues to use decimal.Decimal for string, int and float. – Lin Ma Jun 24 '16 at 06:27
  • 1
    @LinMa: I feel like I'm repeating myself: You **CAN** use Decimal with int, str, and float. Nothing will stop you. It works. **HOWEVER**, floats have limited precision and a binary mantissa. This means that if you use a float to create a Decimal, you will probably not get the result you want. It *works* but it does not do what you *want*. – Dietrich Epp Jun 24 '16 at 14:42
  • 1
    @LinMa: Converting a float to a string **DOES NOT** change the fact that the float has limited precision. For example, `str(0.123456789123456789)` is `'0.12345678912345678'` — you've lost the last digit. If you try to get the last digit back with `'%.18f' % x`, you get `'0.123456789123456784'` instead (it's the wrong number!). If you pass the float to Decimal, you get `Decimal('0.1234567891234567837965840908509562723338603973388671875')` (again, it's the **wrong number**). You will often get the wrong number if you use float, even though it "works". – Dietrich Epp Jun 24 '16 at 14:45
  • @DietrichEpp, thanks a lot and vote up for your both replies. Have a good weekend. – Lin Ma Jun 26 '16 at 04:00

1 Answers1

2

You can do it with Decimal - once you have the number you can play with precision

import decimal   
initial_x='0.123456789123456789'
x=decimal.Decimal(initial_x)
dmitryro
  • 3,463
  • 2
  • 20
  • 28
  • Thanks dmitryro, vote up and wondering if I need to set `prec`? – Lin Ma Jun 23 '16 at 22:36
  • 3
    Passing a float to the `Decimal` constructor means you're throwing away a bunch of precision before you even start. You need to use a string literal. – user2357112 Jun 23 '16 at 22:38
  • 1
    You can do it like decimal.getcontext().prec = 20 - see an example http://learnpythontutorial.blogspot.com/2015/06/python-decimal-module-python-numbers.html – dmitryro Jun 23 '16 at 22:40
  • 1
    String *literal*. Not calling `str` on a float literal. That just throws away even *more* precision. – user2357112 Jun 23 '16 at 22:47
  • 1
    You can use the original float by applying formatting: `decimal.Decimal('%.18f'%x)` – Moses Koledoye Jun 23 '16 at 22:57
  • 1
    @MosesKoledoye: That isn't the original float. That's just a decimal number which is closer to the original float than it is to any other float. – Dietrich Epp Jun 23 '16 at 22:59
  • 1
    @DietrichEpp My `x` refers to the one in OP's post. Wrapping the float with quotes is not something OP might want. – Moses Koledoye Jun 23 '16 at 23:00
  • 2
    @MosesKoledoye: It's still different. You'll get 0.123456789123456784 instead of 0.123456789123456789 (notice the last digit). – Dietrich Epp Jun 23 '16 at 23:02
  • @dmitryro, tried your code and it works even without set `prec`, wondering why? – Lin Ma Jun 23 '16 at 23:14
  • 1
    You specified it as string literal so it works - see the discussion above, but you can play with precision and see what are the different outcomes. – dmitryro Jun 23 '16 at 23:16
  • @dmitryro, thanks and vote up, does it mean if build `Decimal` using string literal, maximum precision will be kept? – Lin Ma Jun 23 '16 at 23:18
  • @DietrichEpp, good catch and vote up your comments. I updated my post with update 1 and you can see using Decimal will have weird output, which `y` has more precision even than original input, wondering why? Thanks. – Lin Ma Jun 23 '16 at 23:18
  • @dmitryro, good catch and vote up your comments. I updated my post with update 1 and you can see using Decimal will have weird output, which `y` has more precision even than original input, wondering why? Thanks. – Lin Ma Jun 23 '16 at 23:19
  • @dmitryro, thanks for all the help, mark your reply as answer. – Lin Ma Jun 24 '16 at 06:28