mathjs
mathjs copied to clipboard
Option to choose default angle units
Thanks for this powerful library. I want to use evaluate
function to compute math expressions.
Certain operators like sin, cos use default unit radian. For example: evaluate(sin(3.14/2))
gives 1. Can I change the default unit to the degree? e.g. evaluate(sin(90))
will give 1.
I think there should be a config to set the default units used in calculations.
You can do evaluate('sin(90 deg)')
for example, would that work for you?
not really. It would be more convenient for me to use directly evaluate('sin(90)')
. A configuration for the default units would be nice
It may be good indeed to reconsider adding support for config options deg//rad/grad. It's quite common for calculators, which is one of the cases where mathjs is often used.
See also this topic where I explain my hesitation in this regard: https://github.com/josdejong/mathjs/issues/944#issuecomment-331626878
Math.js indeed has no configuration for deg/rad. I'm a bit hesitant to implement such a configuration, since it's so easy to make mistakes. I prefer to use explicit units when possible (like
sin(34 deg)
), but this may indeed not be feasible in all cases. I would love to hear more about your use case - maybe we can somehow improve mathjs to accommodate for it.See this example for an idea on how to add support for deg/rad: http://mathjs.org/examples/browser/angle_configuration.html.html
I couldn't understand why "it's so easy to make mistakes". When a user enters expression like "sin(34)" changing them like "sin(34 deg)" for every trigonometric function is hard because there might be nested trigonometric functions. It is also tiring for the eye.
I've made this mistake multiple times in my life doing some calculations with a calculator, and at some point thinking "whuut? there is something weird going on here", only to figure out that I was filling in values in degree whilst the calculator was set to rad or the other way around.
It's a bit similar to implicit multiplication (like 1/2x
) which can bite you too.
I do see the value of it though I'm not a fan of these kind of implicit things myself, I'm open to reconsider adding support for rad/deg/grad after all.
I wish this configuration support was ready. I am Working on a calculator plugin for a CBT system. Over here in Nigeria DEG is the default. I implemented my calculator with a simple evaluate(expression). Works like a charm except I can't set default angles.
I think I need to understand that angles examples first.
@Tobychidi I built a calculator https://github.com/canbax/hasap Here I make a topological sorting of math expressions and then change the angle units one by one https://github.com/canbax/hasap/blob/7d6a28aa1a757e6b536727b5fce2842e00a7f755/src/app/app.component.ts#L513
TL;DR: The reason there is no "degree mode" in mathjs is that it is a very large amount of work, and it's not clear how to get everything consistent (or whether it's possible), and so the payoff has not been worth anyone's effort when it's pretty easy either to just write the units, define your own functions 'cosd' and 'sind' that take degrees, or use one of the other workarounds that have been posted in this issue.
My full thoughts:
I wanted to add that adding a configuration setting for "degree" input to trigonometric functions is not as straightforward as it might seem. In a wide-ranging math library, not only do you have to modify the behavior of the six basic trigonometric functions, but also their inverses. And since we have derivative, well, the derivative of the sine function of angles measured in degrees is not cosine, even if you mean cosine of angles in degrees, it's (π/180)*cosine
. So you have to be very careful to change the derivative operation as well, for all affected functions. And what about polar coordinates? If angles are measured in degrees, all of the polar coordinate functions have to change their behavior as well. And since the exponential function for complex numbers is closely connected with trigonometric functions (exp(ia) = cos a + i sin a), the exponential function has to change its behavior too (euler's formula becomes e^(180*i) + 1 = 0
, for example). And that means that the power and log functions have to change also, so that they are consistent with exp. In fact, the majority of all mathematical operations on complex numbers have to change. I am not actually 100% certain there is a fully consistent set of mathematical operations on real and complex numbers in which one "measures angles in degrees." I think it can be done, but there are many many details that would need tracking down.
So you see, there are very good reasons why mathematics as a whole measures angles in radians, and so why a computer math package that tries to cover a broad range of topics also measures angles in radians. It is very much not just an arbitrary choice.
In fact, I would say that mathjs goes farther than many general math packages in supporting degrees, by allowing expressions like cos(30 deg)
. Now that unicode is essentially universal, would it help to also support cos(30°)
? That would be quite easy and I would be glad to do it if it would be helpful.
Thanks for your input Glen!
On the one side I would love to make this configurable, on the other hand I want to stay away from it because of the complexities it involves.
One idea could be to find a middle way: support configurable angle units for all the "basic" trigonometric functions (sin, cos, tan, asin, acos, atan, etc). And for other functions like the derivative
built a check which just throws an exception when the angle configuration is not rad, saying that it is not supported. It may be tricky to save guard this everywhere though, I'm not sure. What do you think @gwhitney?
The current situation is also not 100% as I would want it, because it is not really symmetric. You can enter cos(30 deg)
, then the output is a number 0.8660254037844387
. But when then calculating acos(0.8660254037844387)
, the response is a number 0.5235987755982987
, which is "just" in rad. I would love to return a unit unit('0.5235987755982987 rad')
, so there cannot be a mistake in that and you can directly convert it to say deg
if you want. Such a feature should probably be behind a feature toggle though (maybe we could use the config predictable=false
for that).
would it help to also support
cos(30°)
?
I like that idea. On my keyboard the character °
is hard to find, so I myself will probably just keep typing deg
, but it reads very nicely, and applications like a calculator could provide a button for it 👍
One more (wild?) idea: currently the mathjs repo offers two setups "full" and "plain number". I can imagine we would provide a new setup "calculator", which offers just basic arithmetic functions, implements this angle config option, and wraps the trigonometric functions to support the config option, like in the example https://mathjs.org/examples/browser/angle_configuration.html.html
the response is a number
0.5235987755982987
, which is "just" in rad. I would love to return a unitunit('0.5235987755982987 rad')
, so there cannot be a mistake in that an
Well the fact is that "rad" is precisely a unitless unit -- it has no dimension. So it should be that acos(sqrt(3)/2) to deg
returns 30 deg
. If it's not that way already, we should be able to make it so without any harm or risk. In other words "1 rad" is precisely the same mathematical entity as 1, for all purposes.
One more (wild?) idea:
I like this idea better than the guard one (it's easier to admit selectively than to weed out) especially if you're willing to have calculator mode not support complex numbers (so we don't have to worry about changing the behavior of exp
).
👍
Well the fact is that "rad" is precisely a unitless unit -- it has no dimension. So it should be that
acos(sqrt(3)/2) to deg
returns30 deg
. If it's not that way already, we should be able to make it so without any harm or risk. In other words "1 rad" is precisely the same mathematical entity as 1, for all purposes.
Good point. Yeah so we could allow converting any number into a unit Deg, so acos(...) to deg
would work. That's an interesting idea.
we could allow converting any number into a unit Deg
Scratch that, darn. What I said was mathematically reasonable, but it doesn't work in the presence of the unit system mathjs has:
sin(tau/4) = sin((tau/4) rad) = sin(90 deg) = 1
and
asin(1) = tau/4 and asin(1) = (tau/4) rad = 90 deg
but
90 deg/secs = (tau/4 rad/secs) = 1/4 hertz
whereas
(tau/4) / secs = 1.57... hertz
So the "pure number" tau/4 unfortuately does not work the same as the "angle" (tau/4) rad in all contexts :-(
So the best we can do is is something like asin(1) rad to deg
which does already work properly.
Incidentally, the conversion 720 deg/secs to hertz
does not currently work in mathjs; should I file a separate issue about that?
wow 🤯 that makes sense. Well, yes, let's leave it up to the user to specify the unit rad
.