Hello everyone.
I need to take the cube root of a number. However, there’s no cube root function simmilar to Mathf.Sqrt, and Math.Pow doesn’t work with values below 1.
What else could I do? ![]()
Thanks in advance.
- Chris
Hello everyone.
I need to take the cube root of a number. However, there’s no cube root function simmilar to Mathf.Sqrt, and Math.Pow doesn’t work with values below 1.
What else could I do? ![]()
Thanks in advance.
Mathf.Pow works fine for this. Just use a fraction of one (one third, for a cube root) as the 2nd param.
Mathf.Pow(myValue, 1f / 3f)
oh, whops, forgot to add the f’s… freaking floating points :s
Oh well, thanks a bunch ![]()
Sorry for the necro, but it using Mathf.Pow() does not work in case of taking the cube root of a negative number. It throws a NaN.
You can’t do Mathf.Pow(-7, 1/3) but you can do Math.cbrt(-7)
The code below will solve the NaN but it is not exactly elegant. Missing feature in the math library?
float CubeRoot(float d) {
if (d < 0.0f) {
return -Mathf.Pow(-d, 1f / 3f);
}
else {
return Mathf.Pow(d, 1f / 3f);
}
}
https://discussions.unity.com/t/674894 Will any officials look at this post?
A bug stuck many people for months.
Also see issuetracking here https://issuetracker.unity3d.com/issues/dot-net-4-dot-6-ios-udpclient-endreceive-fails-with-argumentexception-system-dot-net-dot-socketaddress-is-an-invalid-size
@junestone , I’m confused. Why do you believe this issue is related to Mathf.Pow or taking cube roots? Or are you just hijacking the thread?
Probably an accidental post in the wrong thread. Happened to me too once. Something to do with click-not-look.
Submit it as a bug so they can look at it.
Also, you could condense that
return Mathf.Pow(Mathf.Abs(d), 1f / 3f);
Well mathematically it is correct. Roots of negative values only work with imaginary numbers.
Your example by negating the result if hte value is negative is jsut wrong. If you need it for some purpose you can use that method. Otherwise using Abs() as shown above is an alternative.
Returns NaN?
This possibly handles a value Elecman’s
does not, specifically the value -0, I believe IEEE 754 rules may not let -0 be less than +0 but it is still a negative number which may be an issue?
Well, no, in certain cases (the Nth root where N is an odd integer), the result is real (i.e. the imaginary part is zero). This is one of those cases. The cube root of -8 really is -2, since -2 * -2 * -2 == -8.
I dunno if there may be some complex part due to 1/3 not exactly represented as a floating point
Oh yes, I’m sure this is why the built-in Pow doesn’t even attempt it. Just pointing out that, in a purely mathematical sense, it is a valid thing to ask for in these special cases.
Most likely it is flaoting points. So maybe we need a funtion like this?
Not sure if I goot all the possibilities here.
public float RootX(float f, int degree)
{
if (degree < 1) return float.NaN;
if (f < 0)
{
if (degree % 2 != 1) return float.NaN;
return -UnityEngine.Mathf.Pow(Mathf.Abs(f), 1f / degree);
}
else
return UnityEngine.Mathf.Pow(f, 1f / degree);
}
Seems a bit excessive, what’s wrong with the -3rd root of 3?
And again, not sure but you might need to handle f=-0
Yes, that is what I meant.
In case anyone is wondering, I actually found a real world use case where this is an issue. When solving a Cubic function using the code in the link below, it won’t work in some cases if you replace the Math.cbrt with the Unity suggested alternative.
https://www.cs.rit.edu/~ark/pj/lib/edu/rit/numeric/Cubic.shtml
Solving a Cubic function is needed if you want to reverse solve a Catmull-Rom spline, or in layman’s terms, find x for a certain y on a spline instead of trying a bunch of 0 to 1 spline values and finding the closest one.
May be rewritten as:
float CubeRoot(float d) {
return Mathf.Pow(Mathf.Abs(d), 1f / 3f) * Mathf.Sign(d);
}
Thanks! Without a conditional statement it will faster to execute.
Well, no. This version is more concise and nice to look at, but it will surely be slower than the original.
Mathf.Abs is easy to appear in the Profiler when used extensively (it does some inner calls to the .net “abs” methods). I’m even using my own Abs version which simply returns "a < 0? -a : a". On the other way, Mathf.Sign surely has its internal conditionals too.
My contribution to the thread was not really useful in terms of performance, sorry for that.
Interesting. I use the Abs version in a shader which is much faster than using a conditional statement. But I guess that is to be expected on a GPU.