views:

256

answers:

4

I want to get 1/7 with better precision, but it got truncated. How can I get better precision when I convert a rational number? Thanks.

>>> str(1.0/7)[:50]
'0.142857142857'
+4  A: 

You could multiply the numerator by a large 10^N and stick with arbitrary-precision integers.

EDIT

i mean:

> def digits(a,b,n=50): return a*10**n/b
.
> digits(1,7)
14285714285714285714285714285714285714285714285714L

Python's integers are arbitrary precision. Python's floats are never arbitrary precision. (you'd have to use Decimal, as another answer has pointed out)

Jimmy
+3  A: 

Using Perl (because I can't write Python ;-):

use strict; use warnings;

use integer;

my $x = 1;
my $y = 7;

for (1 .. 50) {
    $x *= 10 if $x < $y;
    my $q = $x / $y;
    $x -= $q * $y;
    print $q;
}

print "\n";
14285714285714285714285714285714285714285714285714

As you can verify by hand, the digits repeat. Printing using "%.50f" will give you the illusion of more precision.

Sinan Ünür
Indeed, all rational numbers eventually repeat.
Keith Randall
This simple method actually works. I will convert it to Python and use it. Thanks.
grokus
@Sinan, I know the digits repeat, but to detect repeating patterns in other rational numbers (1/d where d < 1000), I need more precision.
grokus
@Keith Randall: What do you mean?
Sinan Ünür
@grokus: I was pointing out that the output from using `%.50f` is incorrect.
Sinan Ünür
+1  A: 

With gmpy:

>>> import gmpy
>>> thefraction = gmpy.mpq(1, 7)
>>> hiprecfloat = gmpy.mpf(thefraction, 256)
>>> hiprecfloat.digits(10, 50, -10, 10)
'0.14285714285714285714285714285714285714285714285714'
>>>

You can't do it with normal floats -- they just don't have enough precision for 50 digits! I imagine there's a way to do it (in 2.6 or better) with fractions.Fraction, but I'm not familiar with any way to format it otherwise than as '1/7' (not very useful in your case!-).

Alex Martelli
+1  A: 

Python has a built-in library for arbitrary-precision calculations: Decimal. For example:

>>>from decimal import Decimal, getcontext
>>>getcontext().prec = 50
>>>x = Decimal(1)/Decimal(7)
>>>x
Decimal('0.14285714285714285714285714285714285714285714285714')
>>>str(x)
'0.14285714285714285714285714285714285714285714285714'

Look at the Python Decimal documentation for more details. You can change the precision to be as high as you need.

Daniel G
Thanks. I didn't know about the decimal module. This is the easiest way.
grokus