Search Unity

*SOLVED* Unity Cant Calculate All Decimals in C# ?

Discussion in 'Scripting' started by ErmergerdEnt, Jun 14, 2018.

  1. ErmergerdEnt

    ErmergerdEnt

    Joined:
    Apr 7, 2017
    Posts:
    54
    So I have two drop down menus. Each drop down has 14 options. All options are the same for both drop downs. It's basically a conversion calculator. Converting cm/s2 to let's say km/s2. The calculation to convert lets say 5 centimeters per square second to 5 kilometers per square second would be to times 5 by .00001... the equation I have looks like this..

    Code (CSharp):
    1. if(_AccelerationDropDown1 == 0 && _AccelerationDropDown2 == 7)
    2. {
    3. _AccelerationResult.text = (float.Parse(_AccelerationInput.text) * 0.00001).ToString();
    4. }
    Where value 0 is cm/s2 and value 7 is km/s2. The result I'm getting is 5E-05... I have other equations that are basically the same. Yet they give me actual results like,

    Code (CSharp):
    1. if(_AccelerationDropDown1 == 0 && _AccelerationDropDown2 == 4)
    2. {
    3. _AccelerationResult.text = (float.Parse(_AccelerationInput.text) * 0.0010197).ToString();
    4. }
    This gives me a result of 0.0050985 Grav. I even tried running debug to find the output value and it gives me result equals 5 but the result field said the 5E-05.. I'm trying to figure out why it's not calculating. The answer should be 0.00005.. its kind of weird that itll do the other conversions even though they have more decimal places and not the 0.00001.. any help would be appreciated. Oh and I tried adding F2 inside the string to knock down the decimals but that ended with the same result.
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    My guess is float precision is your hang up. Floats only have precision out to about 7 digits. Try using the Decimal or Double types which have precision out to about 28 and 15 digits respectively.

    Also, I believe when you don't specific a suffix for your decimal number literals they are treated as Double. So your code as written is doing some implicit conversions between floats and doubles. Maybe that is causing some issues when you are pushing the limit of the float type. Don't know, as I'm not really an expert on this topic, but it is something else you can try. I generally use the suffix for literals for whatever type of float like variable I'm using in the same line of code just so there aren't any unnecessary conversions.

    Examples of decimal number literals with type suffixes:
    Code (csharp):
    1. float imAFloat = 1.023f;
    2. double imADouble = 1.023d;
    3. decimal imADecimal = 1.023m;
     
    Last edited: Jun 14, 2018
  3. ErmergerdEnt

    ErmergerdEnt

    Joined:
    Apr 7, 2017
    Posts:
    54
    I ended up just adding "N4". Specifying the amount of decimal placements and changing the float to a decimal. And adding a double variable in place of the .00001

    Code (CSharp):
    1.  
    2. Public Double _AccelDouble = 0.00001
    3.  
    4. if(_AccelerationDropDown1== 0 &&
    5. _AccelerationDropDown2 == 7)
    6. {
    7. _AccelerationResult.text = (decimal.Parse(_AccelerationInput.text) * _accelDouble).ToString("N4");
    8. }
     
    Last edited: Jun 14, 2018
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    You almost certainly don't want to be mixing Doubles with Decimal. Decimal is an exact representation of a fractional number, and it's what you should be using for exact calculations like the ones you're doing. Double/Float are for calculations where small inaccuracies aren't significant. Any reason you're trying to use Double at all here?
     
  5. ErmergerdEnt

    ErmergerdEnt

    Joined:
    Apr 7, 2017
    Posts:
    54
    Well when I did
    Code (CSharp):
    1. public decimal _accelDecimal = 0.00001d;
    It gave me an error that you cant use a float with decimal. So where I have the double at is where I was getting the error. Changing it to double works just fine.
     
  6. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    You're just not declaring your decimal properly. It's "m", not "d":

    Code (CSharp):
    1. public decimal _AccelDouble = 0.00001m;
    2.  
    3. void Update() {
    4.     var someText = (decimal.Parse("123") * _AccelDouble).ToString("N4");
    5. }
     
  7. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Be careful with this. Remember that a computer can only store an infinitesimally small amount of distinct numbers. This is true for both integers and floating point numbers.

    As an example, what would you expect to be the output here and what actually happens? :
    Code (CSharp):
    1. float f1 = 0.1f;
    2. float error = (f1 * 1000.0f) - 100.0f;
    3. Debug.Log(error);
    This is not a Unity, nor even a C#, issue. This is an issue with computers using binary format and there being an infinite range of possible numbers.

    This is exactly why, for example, you shouldn't directly compare floats for equality.
     
  8. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    I am not really sure if I understood your problem correct.. But if the you think something is wrong because 5E-05 seems to be something different than 0.00005 I can tell you good news: there is no problem at all:
    http://lmgtfy.com/?q=5E-05+in+decimal
     
  9. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,037
    Hosnkobf likes this.
  10. ErmergerdEnt

    ErmergerdEnt

    Joined:
    Apr 7, 2017
    Posts:
    54
    @dogoyette I didnt put the decimal.parse in. Thats why i was getting the error. I still had it as float.Parse. Thanks for the clarification. And @Hosnkobf I was getting the return result as 5E-05 instead of a return of 0.00005. Thats because it wasnt reading the decimals places. It was basically saying the return value was to big to generate a return. Making it a decimal instead of a float worked like this.

    Code (CSharp):
    1.  
    2. public decimal _accelerationDecimal = 0.00001m;
    3.  
    4. if (_AcclerationDropDown1.value == 0 && _AccelerationDropDown2.value == 7)
    5.         {
    6.             _AccelerationResult.text = (decimal.Parse(_AccelerationInput.text )  * __accelerationDecimal ).ToString();
    7.             _AccelerationResult.text = _AccelerationInput.text + " " + "cm/s2" + " " + "Converts To" + " " + _AccelerationResult.text + " " + "km/s2";
    8.         }
    And this also worked as well.

    Code (CSharp):
    1.  if (_AcclerationDropDown1.value == 0 && _AccelerationDropDown2.value == 7)
    2.         {
    3.             _AccelerationResult.text = (float.Parse(_AccelerationInput.text )  * 0.00001 ).ToString("N4");
    4.             _AccelerationResult.text = _AccelerationInput.text + " " + "cm/s2" + " " + "Converts To" + " " + _AccelerationResult.text + " " + "km/s2";
    5.         }
     
  11. ErmergerdEnt

    ErmergerdEnt

    Joined:
    Apr 7, 2017
    Posts:
    54
    Just an update, I ended up using this instead. I just made a string and declared it to hold commas in larger outputs and set the decimal place to 12 for the larger decimal calculations. Then I simply declared the input and result texts to be doubles and then set it to the Format string. If that makes sense lol. Thanks for all y'alls help btw.

    Code (CSharp):
    1. private const string Format = ("#,#.############");
    2.  
    3. if (_AcclerationDropDown1.value == 0 && _AccelerationDropDown2.value == 7)
    4.         {
    5.             _AccelerationResult.text = (float.Parse(_AccelerationInput.text )  * 0.00001 ).ToString();
    6. double a = double.Parse(_AccelerationResult.text);
    7. double b = double.Parse(_AccelerationInput.text);
    8. _AccelerationResult.text = b.ToString(Format) + " " + "cm/s2" + " " + "Converts To" + " " + a.ToString(Format) + " " + "km/s2";
    9.         }
     
  12. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Do what you want, but I don't understand why you're so insistent on using Doubles/Floats for this. Decimal is designed for this kind of exact numeric representation, Double is not. It's like you've intentionally decided to compute incorrect answers, and them round them until they look correct. So while that might show you a reasonable approximation for .1f (which is actually something like .10000000000003), what's going to happen for values like .01 (which wikipedia says is actually represented by floating point as 0.009999999776482582092285156250) ?

    Again, you're making this harder for yourself by using the wrong data type.
     
    Last edited: Jun 15, 2018
  13. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Yeah I'd really just switch everything to decimal and be done with it. It is a trivial amount of extra memory usage.