I'm just getting into Unity and C#, trying to code a script for calculator with 2 input fields, buttons for necessary arithmetic operations and a "Result" text field. All basic functions are working fine, but while messing with the input values for Power I encountered this issue of overflowing value in resulting variable. Googling various solutions I settled with this one shown in the code below. Problem is, mentioned issue still persists, and when testing the app I am still getting this error in the console:
OverflowException: Arithmetic operation resulted in an overflow. System.Decimal.op_Explicit (System.Single value) (at <695d1cc93cca45069c528c15c9fdd749>:0)
I assume that the way checked-keyword is implemented in my code might be incorrect, but I can't figure out in what way.
My initial idea was to convert resulting value to double and set a ceiling for it, but as I understand the calculation still being done and overflow happens before I even compare value to the threshold, so it was decided to try other tools. If any other ways to avoid this error exist - it would be awesome.
public class Calculator : MonoBehaviour
{
public Text Result;
public InputField FirstNumber;
public InputField SecondNumber;
public void OnClickPower()
{
if (FirstNumber.text.ToString() != "" & SecondNumber.text.ToString() != "")
{
Debug.Log("Numbers Unequal > success");
decimal i = decimal.MaxValue;
int j;
float k;
j = int.Parse(FirstNumber.text);
Debug.Log("First number > " j);
j = int.Parse(FirstNumber.text);
Debug.Log("Second number > " j);
k = Mathf.Pow(float.Parse(FirstNumber.text), float.Parse(SecondNumber.text));
Debug.Log("Result in float > " k);
decimal l = Convert.ToDecimal(k);
Debug.Log("Result in decimal > " l);
try
{
l = checked(i l);
Result.text = l.ToString();
}
catch (OverflowException ex)
{
Debug.Log(ex);
Result.text = l.ToString();
}
}
else
{
Result.text = "NO NUMBERS";
}
}
};
CodePudding user response:
This might fix some issues. I would also suggest the changes to the if statement. I think in unity Mathf.Pow is what's used for float since it has its own Math for floats. I can't post comments but, why are you adding the max value of decimal to your converted float? That will guarantee an overflow every time I would think. Like you said the checked should be used like this but, I doubt Unity lets you get away with it? I don't know if I have ever needed to use the checked keyword.
if (!string.IsNullOrEmpty(FirstNumber.text.ToString()) & !string.IsNullOrEmpty(SecondNumber.text.ToString()))
{
Debug.Log("Numbers Unequal > success");
decimal i = decimal.MaxValue;
int j;
float k;
j = int.Parse(FirstNumber.text);
Debug.Log("First number > " j);
//You Had First number here.
j = int.Parse(SecondNumber.text);
Debug.Log("Second number > " j);
k = Mathf.Pow(float.Parse(FirstNumber.text), float.Parse(SecondNumber.text));
Debug.Log("Result in float > " k);
decimal l = Convert.ToDecimal(k);
Debug.Log("Result in decimal > " l);
try
{
checked
{
l = i l;
Result.text = l.ToString();
}
}
catch (OverflowException ex)
{
Debug.Log(ex);
Result.text = l.ToString();
}
}
else
{
Result.text = "NO NUMBERS";
}
CodePudding user response:
Use System.Math
instead of Mathf
if you need to handle very large values because double
supports larger values than float
.
As for checking if the result will overflow, just don't use Pow
until you determine if it's safe. Think back to algebra. You can check Math.Log(Double.MaxValue, base)
and if the result is less than exponent
then you can know that Math.Pow(base, exponent)
will be greater than the max value, which means it will overflow.
For example:
// Avoid shadowing Unity's Random if you're using it.
using Math = System.Math;
// ...
double baseVal = Double.Parse(FirstNumber.text);
Debug.Log("First number > " baseVal);
double exponent = Double.Parse(SecondNumber.text);
Debug.Log("Second number > " exponent);
if (Math.Log(Double.MaxValue, baseVal) < exponent)
{
// a pow would overflow, so
// do something reasonable
return;
}
double k = Math.Pow(baseVal, exponent);
Debug.Log("Result in double > " k);