Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

answered 2010-12-30 16:37:57 -0500

DSM gravatar image

In the show-your-work spirit, here was my line of thought. First, I thought that maybe all that was missing was adding a .n method to degree, to get degree to pretend as if it were pi/180, but that didn't work like I was hoping. Then I realized that this was silly: pi already behaves the way I want it to, I just want to define a new pi-like constant with name "degree" and value "pi/180". So looking at how pi is implemented, it subclasses Constant and then takes the expression from that. So in a similar spirit:


from sage.symbolic.constants import Constant

class ConstantFromExpression(Constant):
    def __init__(self, name, expr):
        conversions = dict(maxima=repr(maxima.coerce(expr)))
        Constant.__init__(self, name,conversions=conversions)
        self._expr = expr
    def __float__(self): return float(self._expr)
    def _mpfr_(self, R): return R(self._expr)
    def _real_double_(self, R): return R(self._expr)
    def __complex__(self, C): return C(self._expr)

def NamedExpression(name, expr):
    return ConstantFromExpression(name,expr).expression()

which should allow you to do what you want:


sage: degree = NamedExpression('degree', pi/180)
sage: degree
degree
sage: float(degree)
0.017453292519943292
sage: 
sage: sin(25*degree)
sin(25*degree)
sage: a = sin(25*degree)
sage: a.n()
0.422618261740699
sage: RealField(100)(a)
0.42261826174069943618697848965
sage: 
sage: sin(90*degree)
sin(90*degree)
sage: simplify(sin(90*degree))
1
sage: sin(45*degree)
sin(45*degree)
sage: simplify(sin(45*degree))
1/2*sqrt(2)

There are lots of conversions and features I didn't implement, of course, but I had to do at least the maxima one to get simplify to work correctly. I don't know enough about the maxima coercion repr to trust it entirely -- should probably put some tests in, to make sure the result tests equal to the input. But for this trivial case, it seems to work okay.

Maybe a NamedExpression wrapper would be useful?

In the show-your-work spirit, here was my line of thought. First, I thought that maybe all that was missing was adding a .n method to degree, to get degree to pretend as if it were pi/180, but that didn't work like I was hoping. Then I realized that this was silly: pi already behaves the way I want it to, I just want to define a new pi-like constant with name "degree" and value "pi/180". So looking at how pi is implemented, it subclasses Constant and then takes the expression from that. So in a similar spirit:


from sage.symbolic.constants import Constant

class ConstantFromExpression(Constant):
    def __init__(self, name, expr):
        conversions = dict(maxima=repr(maxima.coerce(expr)))
        Constant.__init__(self, name,conversions=conversions)
        self._expr = expr
    def __float__(self): return float(self._expr)
    def _mpfr_(self, R): return R(self._expr)
    def _real_double_(self, R): return R(self._expr)
    def __complex__(self, C): return C(self._expr)

def NamedExpression(name, expr):
    return ConstantFromExpression(name,expr).expression()

which should allow you to do what you want:


sage: degree = NamedExpression('degree', pi/180)
sage: degree
degree
sage: float(degree)
0.017453292519943292
sage: 
sage: sin(25*degree)
sin(25*degree)
sage: a = sin(25*degree)
sage: a.n()
0.422618261740699
sage: RealField(100)(a)
0.42261826174069943618697848965
sage: 
sage: sin(90*degree)
sin(90*degree)
sage: simplify(sin(90*degree))
1
sage: sin(45*degree)
sin(45*degree)
sage: simplify(sin(45*degree))
1/2*sqrt(2)

There are lots of conversions and features I didn't implement, of course, but I had to do at least the maxima one to get simplify to work correctly. I don't know enough about the maxima coercion repr to trust it entirely -- should probably put some tests in, to make sure the result tests equal to the input. But for this trivial case, it seems to work okay.

Maybe a NamedExpression wrapper would be useful?

In the show-your-work spirit, here was my line of thought. First, I thought that maybe all that was missing was adding a .n method to degree, to get degree to pretend as if it were pi/180, but that didn't work like I was hoping. Then I realized that this was silly: pi already behaves the way I want it to, I just want to define a new pi-like constant with name "degree" and value "pi/180". So looking at how pi is implemented, it subclasses Constant and then takes the expression from that. So in a similar spirit:


from sage.symbolic.constants import Constant

class ConstantFromExpression(Constant):
    def __init__(self, name, expr):
        conversions = dict(maxima=repr(maxima.coerce(expr)))
        Constant.__init__(self, name,conversions=conversions)
        self._expr = expr
    def __float__(self): return float(self._expr)
    def __complex__(self): return complex(self._expr)
    def _mpfr_(self, R): return R(self._expr)
    def _real_double_(self, R): return R(self._expr)

def NamedExpression(name, expr):
    return ConstantFromExpression(name,expr).expression()

which should allow you to do what you want:


sage: degree = NamedExpression('degree', pi/180)
sage: degree
degree
sage: float(degree)
0.017453292519943292
sage: 
sage: sin(25*degree)
sin(25*degree)
sage: a = sin(25*degree)
sage: a.n()
0.422618261740699
sage: RealField(100)(a)
0.42261826174069943618697848965
sage: 
sage: sin(90*degree)
sin(90*degree)
sage: simplify(sin(90*degree))
1
sage: sin(45*degree)
sin(45*degree)
sage: simplify(sin(45*degree))
1/2*sqrt(2)

There are lots of conversions and features I didn't implement, of course, but I had to do at least the maxima one to get simplify to work correctly. I don't know enough about the maxima coercion repr to trust it entirely -- should probably put some tests in, to make sure the result tests equal to the input. But for this trivial case, it seems to work okay.

Maybe a NamedExpression wrapper would be useful?