bug/feature? increasing precision of a complex number

1 view
Skip to first unread message

ggrafendorfer

unread,
Dec 27, 2008, 8:11:22 PM12/27/08
to sage-support
Hi Developers, (sage 3.2.2 on a 32-bit Athlon running Debian etch)
I would report it to trac (tell me if I should), but I'm not sure if
it's a bug,

increasing precision of a complex number which has imaginary part zero
results in a real number:

this works:
sage: a = CC(-5. + I*0.0001).n(prec=100)
sage: type(a)
<type 'sage.rings.complex_number.ComplexNumber'>
sage: a.prec()
100

but here a turns into a real number:
sage: a = CC(-5 + I*0.).n(prec=100)
sage: type(a)
<type 'sage.rings.real_mpfr.RealNumber'>
sage: a.prec()
100

if this is a feature, than it's annoying, for example taking the
logarithm of -5 with precision 100 than leads to

sage: ln(CC(-5).n(prec=100))
NaN

I know how to do it the right way (ln(ComplexField(100)(-5)), but the
above should work too, or?

Georg

William Stein

unread,
Dec 28, 2008, 10:09:05 PM12/28/08
to sage-s...@googlegroups.com

You should do it the right way instead of the wrong way. It is a very
bad idea to do stuff like "ln(CC(-5).n(prec=100))", which basically
says "take -5, think of it as a complex number with 53 bits of
precision, take the log, then view the answer as magically having 100
bits of precision by basically randomly making up the missing 47
bits".

William

ggrafendorfer

unread,
Dec 29, 2008, 11:55:23 AM12/29/08
to sage-support

> You should do it the right way instead of the wrong way. It is a very
> bad idea to do stuff like "ln(CC(-5).n(prec=100))", which basically
> says "take -5, think of it as a complex number with 53 bits of
> precision, take the log, then view the answer as magically having 100
> bits of precision by basically randomly making up the missing 47
> bits".

Dear William,
With "ln(CC(-5).n(prec=100))" I'm not taking the log of a number with
53-bit precision hoping that it magically turns into a 100-bit
precision number, what you mean would be "ln(CC(-5)).n(prec=100)",
I'm taking the log of CC(-5).n(prec=100) which obviously should be a
100-bit precision number,


But the main question actually was if it's a desired behauviour that CC
(-5).n(prec=100) is a real number:

sage: type(CC(-5).n(prec=100))
<type 'sage.rings.real_mpfr.RealNumber'>

increasing precision of a complex number should not change it's type,
or?

Georg

mabshoff

unread,
Dec 29, 2008, 12:07:15 PM12/29/08
to sage-support


On Dec 29, 8:55 am, ggrafendorfer <georg.grafendor...@gmail.com>
wrote:

Hi Georg,

> > You should do it the right way instead of the wrong way.  It is a very
> > bad idea to do stuff like "ln(CC(-5).n(prec=100))", which basically
> > says "take -5, think of it as a complex number with 53 bits of
> > precision, take the log, then view the answer as magically having 100
> > bits of precision by basically randomly making up the missing 47
> > bits".
>
> Dear William,
> With "ln(CC(-5).n(prec=100))" I'm not taking the log of a number with
> 53-bit precision hoping that it magically turns into a 100-bit
> precision number, what you mean would be "ln(CC(-5)).n(prec=100)",
> I'm taking the log of CC(-5).n(prec=100) which obviously should be a
> 100-bit precision number,

Look at "CC?" - the CC field is 53 bits of precision. If you want more
looks at ComplexField?

> But the main question actually was if it's a desired behauviour that CC
> (-5).n(prec=100) is a real number:
>
> sage: type(CC(-5).n(prec=100))
> <type 'sage.rings.real_mpfr.RealNumber'>
>
> increasing precision of a complex number should not change it's type,
> or?

Well, you are asking for a numerical approximation here of "-5" in the
complex field. I am not sure this is a bug when the value is returned
in the "smaller" field.

> Georg

I am not 100% sure we are actually trying to solve the same issue:
This is what you get:

sage: a = CC(1/3).n(prec=200)
sage: a
0.33333333333333300000000000000000000000000000000000000000000

and the precision is not 200 correct bits, but 53 correct bits and
zeroes filled in. This is the point William was trying to make AFAIK.

What you might want is this:

sage: b=ComplexField(200)
sage: b
Complex Field with 200 bits of precision
sage: b=1/3;b
1/3
sage: b.n(prec=200)
0.33333333333333333333333333333333333333333333333333333333333

In the above case you get 200 bits of precision.

Cheers,

Michael

Alex Ghitza

unread,
Dec 29, 2008, 12:40:01 PM12/29/08
to sage-s...@googlegroups.com
> Dear William,
> With "ln(CC(-5).n(prec=100))" I'm not taking the log of a number with
> 53-bit precision hoping that it magically turns into a 100-bit
> precision number, what you mean would be "ln(CC(-5)).n(prec=100)",
> I'm taking the log of CC(-5).n(prec=100) which obviously should be a
> 100-bit precision number,

Look at "CC?" - the CC field is 53 bits of precision. If you want more
looks at ComplexField?


At the risk of belabouring the point that William and Michael have already made: you start with -5 which is an exact number, but as soon as you do CC(-5) you get a complex number with 53 bits of precision and no memory of where it's coming from.  So doing CC(-5).n(prec=100) will just fill the missing 47 bits with randomness, just as if you had done CC(-12.98601).n(prec=100).

Best,
Alex

--
Alex Ghitza -- Lecturer in Mathematics -- The University of Melbourne -- Australia -- http://www.ms.unimelb.edu.au/~aghitza/

John Cremona

unread,
Dec 29, 2008, 12:40:33 PM12/29/08
to sage-s...@googlegroups.com
There really are two different issues here. The one which William and
Michael concentrate on is that adding .n(100) to a 53-bit complex
number does not increase its precision in any meaningful sense, it
just pads with 47 bits of 0.

But the second point is to do with Georg's original observation that
sage: type(CC(1/3 + 0.0*I))
<type 'sage.rings.complex_number.ComplexNumber'>
sage: type(CC(1/3 + 0.0*I).n(100))
<type 'sage.rings.real_mpfr.RealNumber'>

or perhaps more clearly,
sage: z = CC(1/3 + 0.0*I)
sage: type(z)
<type 'sage.rings.complex_number.ComplexNumber'>
sage: type(z.n(10))
<type 'sage.rings.real_mpfr.RealNumber'>

so that the return type of .n() is real.

John Cremona

2008/12/29 mabshoff <Michael...@mathematik.uni-dortmund.de>:

John Cremona

unread,
Dec 29, 2008, 12:45:27 PM12/29/08
to sage-s...@googlegroups.com
2008/12/29 John Cremona <john.c...@gmail.com>:
> There really are two different issues here. The one which William and
> Michael concentrate on is that adding .n(100) to a 53-bit complex
> number does not increase its precision in any meaningful sense, it
> just pads with 47 bits of 0.
>
> But the second point is to do with Georg's original observation that
> sage: type(CC(1/3 + 0.0*I))
> <type 'sage.rings.complex_number.ComplexNumber'>
> sage: type(CC(1/3 + 0.0*I).n(100))
> <type 'sage.rings.real_mpfr.RealNumber'>
>
> or perhaps more clearly,
> sage: z = CC(1/3 + 0.0*I)
> sage: type(z)
> <type 'sage.rings.complex_number.ComplexNumber'>
> sage: type(z.n(10))
> <type 'sage.rings.real_mpfr.RealNumber'>
>
> so that the return type of .n() is real.

Looking at the code for numerical_approx() in sage.misc.functional,
this happens because the attempt to coerce z into RealField(10)
succeeds. To fix this (if it is agreed that it is a bug) that
function would need to test the type of the input and return something
of the same type (real/complex).

John

mabshoff

unread,
Dec 29, 2008, 12:48:29 PM12/29/08
to sage-support


On Dec 29, 9:40 am, "John Cremona" <john.crem...@gmail.com> wrote:
> There really are two different issues here.  The one which William and
> Michael concentrate on is that adding .n(100) to a 53-bit complex
> number does not increase its precision in any meaningful sense, it
> just pads with 47 bits of 0.
>
> But the second point is to do with Georg's original observation that
>  sage: type(CC(1/3 + 0.0*I))
> <type 'sage.rings.complex_number.ComplexNumber'>
> sage: type(CC(1/3 + 0.0*I).n(100))
> <type 'sage.rings.real_mpfr.RealNumber'>
>
> or perhaps more clearly,
> sage: z = CC(1/3 + 0.0*I)
> sage: type(z)
> <type 'sage.rings.complex_number.ComplexNumber'>
> sage: type(z.n(10))
> <type 'sage.rings.real_mpfr.RealNumber'>
>
> so that the return type of .n() is real.
>
> John Cremona

Yeah, that is kind of obvious now that I look at it again :)

Maybe the docstring out to be cleaned up and clearly state that the
returned type is a real since it currently does not:

sage: a.n?
Type: builtin_function_or_method
Base Class: <type 'builtin_function_or_method'>
String Form: <built-in method n of
sage.rings.complex_number.ComplexNumber object at 0x7f23df3c44d0>
Namespace: Interactive
Docstring:

Return a numerical approximation of x with at least prec
bits of
precision.

EXAMPLES:
sage: (2/3).n()
0.666666666666667
sage: a = 2/3
sage: pi.n(digits=10)
3.141592654
sage: pi.n(prec=20) # 20 bits
3.1416

Class Docstring:
<attribute '__doc__' of 'builtin_function_or_method' objects>



To create elements in higher precision rings you should use something
like the following and not what I gave as an example earlier:

sage: CC200=ComplexField(200)
sage: b=CC200(1/3,1/7)
sage: b
0.33333333333333333333333333333333333333333333333333333333333 +
0.14285714285714285714285714285714285714285714285714285714286*I

Cheers,

Michael

William Stein

unread,
Dec 29, 2008, 12:54:26 PM12/29/08
to sage-s...@googlegroups.com
On Mon, Dec 29, 2008 at 9:48 AM, mabshoff
<Michael...@mathematik.uni-dortmund.de> wrote:
>
>
>
> On Dec 29, 9:40 am, "John Cremona" <john.crem...@gmail.com> wrote:
>> There really are two different issues here. The one which William and
>> Michael concentrate on is that adding .n(100) to a 53-bit complex
>> number does not increase its precision in any meaningful sense, it
>> just pads with 47 bits of 0.
>>
>> But the second point is to do with Georg's original observation that
>> sage: type(CC(1/3 + 0.0*I))
>> <type 'sage.rings.complex_number.ComplexNumber'>
>> sage: type(CC(1/3 + 0.0*I).n(100))
>> <type 'sage.rings.real_mpfr.RealNumber'>
>>
>> or perhaps more clearly,
>> sage: z = CC(1/3 + 0.0*I)
>> sage: type(z)
>> <type 'sage.rings.complex_number.ComplexNumber'>
>> sage: type(z.n(10))
>> <type 'sage.rings.real_mpfr.RealNumber'>
>>
>> so that the return type of .n() is real.
>>
>> John Cremona
>
> Yeah, that is kind of obvious now that I look at it again :)
>
> Maybe the docstring out to be cleaned up and clearly state that the
> returned type is a real since it currently does not:

The return type is real if the input number can be coerced to a real
with that many digits of precision. Otherwise it is complex.

I personally think it would be reasonable to consider this a bug and
change the numerical_approx function to return a complex number when
the input is complex, as the original poster requested. Two reasons:

(1) he gives a good example to illustrate how some code is more
complicated if we do not change the behavior of n(). It's best if
that complexity is in n() rather than user code.

(2) mathematica does this:
sage: mathematica('1 + 0.0*I').N()
1. + 0.*I


-- William
--
William Stein
Associate Professor of Mathematics
University of Washington
http://wstein.org

ggrafendorfer

unread,
Dec 29, 2008, 6:19:19 PM12/29/08
to sage-support
Hi All,
thanks for all the answers, especially for John Cremona for being the
only one recognizing what I actually wanted to point out :-)
It's probably my fault, I'll take away obscuring examples the next
time and try to focus on the issue

For better understanding why I did "CC(-5).n(prec=100)" instead of the
better "ComplexField(100)(-5)":

Originally I just wanted the log of -5, but ln(-5) gives a "value
error" and ln(-5.) returns NaN,
so I wrote ln(CC(-5)) which works and returns a complex number, then I
wanted to increase the precision of the result,
and as -5 can be represented precisely in binary system I just wrote CC
(-5).n(prec=100) which is the same as ComplexField(100)(-5) except
that the number types are different:

sage: a = CC(-5).n(prec=100)
sage: b = ComplexField(100)(-5)
sage: a == b
True
sage: type(a) == type(b)
False
sage: ln(a)
NaN
sage: ln(b)
1.6094379124341003746007593332 + 3.1415926535897932384626433833*I

Georg

John Cremona

unread,
Dec 30, 2008, 4:30:21 AM12/30/08
to sage-s...@googlegroups.com
2008/12/29 ggrafendorfer <georg.gra...@gmail.com>:
I think that is a very good example, showing more clearly than the
original post what the problem is, and convincing me that the
behaviour of .n() should be changed as discussed earlier. I am
opening a ticket for this now.

John


>
> Georg
> >
>

John Cremona

unread,
Dec 30, 2008, 4:38:16 AM12/30/08
to sage-s...@googlegroups.com
2008/12/30 John Cremona <john.c...@gmail.com>:

>
> I think that is a very good example, showing more clearly than the
> original post what the problem is, and convincing me that the
> behaviour of .n() should be changed as discussed earlier. I am
> opening a ticket for this now.
>

http://trac.sagemath.org/sage_trac/ticket/4892

> John
>
>
>>
>> Georg
>> >>
>>
>
Reply all
Reply to author
Forward
0 new messages