# Conversion fraction field(QQ[X]) to fraction field(ZZ[X])

How to I convert an element of the fraction field of QQ[X] to the fraction field of ZZ[X]?

sage: R.<x> = ZZ[]
sage: F = R.fraction_field()
sage: e = (1/2)/(x+1)
sage: e.parent()
Fraction Field of Univariate Polynomial Ring in x over Rational Field
sage: F(e)
Traceback (most recent call last):
...
TypeError: no conversion of this rational to integer


In my use case, e is the result of a lengthy computation where at some point beyond my control the result was coerced into QQ[X]. In my particular case, I prefer the fraction field of ZZ[X] because the output is nicer.

edit retag close merge delete

Sort by » oldest newest most voted

A hack would be to factor e and get the unit and the factors. For instance:

sage: R.<x> = ZZ[]
sage: F = R.fraction_field()
sage: e = (1/2)/(x+1)
sage: ef = e.factor()    # e factorized, as an instance of the class
sage: ef.parent()
<class 'sage.structure.factorization.Factorization'>
sage: ef.unit()
1/2
sage: ef.__dict__
{'_Factorization__cr': False,
'_Factorization__unit': 1/2,
'_Factorization__universe': Univariate Polynomial Ring in x over Rational Field,
'_Factorization__x': [(x + 1, -1)]


Just a hack. An other one would be to get the lcm of the denominators of the coefficients appearing in the fraction. Explicitly. Here is an awful example, taken so to test if things work in a real mess.

sage: v = ( 1/6 * x^2 + 1/7 *x - 1/199 ) / (x+1/17) / 6 / (1/11*x+3/29)
sage: v
(1/6*x^2 + 1/7*x - 1/199)/(6/11*x^2 + 3540/5423*x + 18/493)
sage: vn = v.numerator()
sage: vd = v.denominator()
sage: vn, vd
(1/6*x^2 + 1/7*x - 1/199, 6/11*x^2 + 3540/5423*x + 18/493)
sage: vn.coefficients(), vd.coefficients()
([-1/199, 1/7, 1/6], [18/493, 3540/5423, 6/11])
sage: vnlcm = lcm( [ c.denominator() for c in vn.coefficients() ] )
sage: vdlcm = lcm( [ c.denominator() for c in vd.coefficients() ] )
sage: vnlcm, vdlcm
(8358, 5423)
sage: F( (vn*vnlcm) / (vd*vdlcm) )
(1393*x^2 + 1194*x - 42)/(2958*x^2 + 3540*x + 198)
sage: vdlcm / vnlcm * _ == v
True

more

I know, it is not a good idea to look into the __dict__, the internal representation may change in time. But this one particular __dict__ is very stable.

Rescaling numerator and denominator by the lcm of the denominators of the coefficients is the right thing to do:

sage: S=ZZ['x'].fraction_field()
sage: D=lcm([u.denominator() for u in e.numerator().coefficients() + e.denominator().coefficients()])
sage: S(D*e.numerator())/S(D*e.denominator())
1/(2*x + 2)


However, there is something much worse here:

sage: R=QQ['x'].fraction_field()
sage: a=(1/2)/(R.0+1)
sage: b=(1)/(2*R.0+2)
sage: a,b
(1/2/(x + 1), 1/(2*x + 2))
sage: a==b
True
sage: hash(a) == hash(b)
False


more