sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.47k stars 485 forks source link

Conversion RR -> QQ wrong for exact integers #16769

Open jdemeyer opened 10 years ago

jdemeyer commented 10 years ago

This real number can be exactly represented by the integer (and also rational) 2^54, so this is off by one:

sage: QQ(RR(2^54))
18014398509481983

The underlying function called by QQ() is simplest_rational:

sage: RR(2^54).simplest_rational()
18014398509481983

It must be said that this result agrees with the definition of "simplest rational", so perhaps the definition is wrong.

Component: basic arithmetic

Issue created by migration from https://trac.sagemath.org/ticket/16769

jdemeyer commented 10 years ago

Description changed:

--- 
+++ 
@@ -11,3 +11,5 @@
 sage: RR(2^54).simplest_rational()
 18014398509481983

+ +It must be said that this result agrees with the definition of "simplest rational", so perhaps the definition is wrong.

61ec4b54-b7da-46f2-b899-fcb8309bbc50 commented 8 years ago
comment:3

RR(2^54) is an exact integer although not an instance of Integer here. Conversion of RealNumber to Rational should yield its integral value. What if we check whether RR(2^54) or any RealNumber in general is an exact integer before returning it as Rational ?

jdemeyer commented 8 years ago
comment:4

Replying to @sagetrac-ajagekar-akshay:

RR(2^54) is an exact integer although not an instance of Integer here. Conversion of RealNumber to Rational should yield its integral value. What if we check whether RR(2^54) or any RealNumber in general is an exact integer before returning it as Rational ?

That would solve this particular case but I'm doubting if that is general enough.

61ec4b54-b7da-46f2-b899-fcb8309bbc50 commented 8 years ago
comment:5

Replying to @jdemeyer:

Replying to @sagetrac-ajagekar-akshay:

RR(2^54) is an exact integer although not an instance of Integer here. Conversion of RealNumber to Rational should yield its integral value. What if we check whether RR(2^54) or any RealNumber in general is an exact integer before returning it as Rational ?

That would solve this particular case but I'm doubting if that is general enough.

Can you give some examples where this will not work ?

nbruin commented 8 years ago
comment:6

Any element of RR of absolute value at least 252 can be expressed "exactly" as an integer:

sage: a=RR(2^52)
sage: s,m,e=a.sign_mantissa_exponent()
sage: s,m,e
(1, 4503599627370496, 0)
sage: s*m*2^e == a
True

simply because e will be non-negative for such numbers. Indeed, any float can be expressed exactly as a rational number: it's the number s*m*2^e that is used internally. The reason why we're not using that is basically this:

sage: a=RR(1/3)
sage: s,m,e=a.sign_mantissa_exponent()
sage: s*m*2^e
6004799503160661/18014398509481984

It's much nicer to get 1/3 back.

Indeed, the definition of "simplest rational" doesn't seem so useful anymore by the time you enter the range where the denominator is guaranteed to be 1. However, depending on getting an exact number back after going through RR is almost certainly a bug somewhere. So I don't think we should go out of our way to guarantee it. If you absolutely want access to the internal representation, there's sign_mantissa_exponent anyway.

The key is, the map ZZ->RR is not injective. So any section in the other direction is not going to compose to the identity on ZZ. It's basically an implementation detail that ZZ(2^54) maps to an element in RR that internally is represented by something that amounts to exactly that integer.