Search Unity

"float.TryParse()" not working as expected

Discussion in 'Scripting' started by LucasJSR, Jan 17, 2022.

  1. LucasJSR

    LucasJSR

    Joined:
    Aug 15, 2020
    Posts:
    13
    Hello everyone!

    I have a C# script that gets float and datetime values from a MySQL table (through a PHP file) as a single string, and then splits it into multiple elements of a string array. What I do next is look at each element of this array and check if its a float number or a datetime value, which is done through the "float.TryParse()" method. If it's a float, it adds the value (converted to float) to the "valuesVar" list. If it's a datetime value, it is added to the "datetimeVar" list.

    My problem is that the "float.TryParse" method only seems to return "true" if the string contains an integer: of all the numeric values that I'm accessing in the table, only one is an integer, and only this value is being added to the "valuesVar" list. Here is my code:

    Code (CSharp):
    1.         WWWForm form = new WWWForm();
    2.         form.AddField("id_var", varSelected);
    3.  
    4.         UnityWebRequest request = UnityWebRequest.Post("http://localhost/VC3_proto/history_connect.php", form);
    5.         yield return request.SendWebRequest();
    6.  
    7.         string[] results = request.downloadHandler.text.Split('\n');
    8.  
    9.         foreach (string s in results)
    10.         {
    11.  
    12.             float i = 0;
    13.             bool isNum = float.TryParse(s, out i);
    14.  
    15.             Debug.Log(isNum);
    16.  
    17.             if (s != "")
    18.             {
    19.  
    20.                 if (isNum == true)
    21.                 {
    22.  
    23.                     valuesVar.Add(i);
    24.  
    25.                 }
    26.  
    27.                 else
    28.                 {
    29.  
    30.                     datetimeVar.Add(s);
    31.  
    32.                 }
    33.  
    34.             }
    35.  
    36.  
    Is the "float.TryParse()" method supposed to behave like this? Or am I doing something wrong?

    Thanks in advance.
     
  2. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,647
    What do the strings look like? It's hard to tell what the problem could be without knowing the input and output.
     
    LucasJSR likes this.
  3. Kurt-Dekker and LucasJSR like this.
  4. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,341
    Maybe you are parsing it with a none english language variant (c# does use your local culture settings by default). Try this:
    Code (CSharp):
    1. float test;
    2. if (float.TryParse(xPos, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out test) == false)
    3. {
    4.     test = 0f; // your default value if parsing fails (which will happen if the numer format diverges from the standard "." for comma syntax).
    5. }
    If you want more info on why all that culture business is necessary then look here: https://forum.unity.com/threads/float-parse-isnt-really-working.1141750/#post-7331416
     
    PraetorBlue, LucasJSR and Bunny83 like this.
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,000
    Yep, that would be my first assumption as well. Even if he isn't, running this code on a user's device would change how the numbers are parsed. When it comes to serialization of any kind, always use the invariant culture.
     
    LucasJSR and _geo__ like this.
  6. LucasJSR

    LucasJSR

    Joined:
    Aug 15, 2020
    Posts:
    13
    Hi everyone! Thanks a lot for the replies.

    You're right, sorry about that. The strings returned by the php file have this basic structure: "value" + "\n" + "datetime" + "\n". The "\n" character is used as the split delimiter on the C# script. Basically, the string looks like that:

    "90.2
    2021-12-05 11:30:36
    112.6
    2021-12-05 12:49:20
    etc...."

    Thank you, that fixed it! Strangely enough, the decimal numbers that I'm accessing already use a decimal point (e.g. 90.5), but after the parsing they are stored in the list with a comma (e.g. 90,5). Is it because of my local culture settings?
     
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,000
    Yes, that was our whole point ^^. When you convert your number into a string you should also use the invariant culture. When you don't specify one, it uses the local culture setting. So it's possible that it works on one machine but breaks on another. For example I'm here in germany and we use the comma as decimal point. It's the same with france and spain and several others. In essence half the world uses a point, the other half uses the comma ^^.

    As I said above when it comes to serialization, especially when the data is transferred to another machine, you should always use the invariant culture. This is almost identical with the US culture, but is guaranteed to never change. Culture habits can change over the course of decades / centuries / millenia. The invariant culture ensures to always produce the same result on all machines.

    The float.ToString method has several overloads. There's also some that take an IFormatProvider.
     
    LucasJSR likes this.
  8. LucasJSR

    LucasJSR

    Joined:
    Aug 15, 2020
    Posts:
    13
    I see! Thank you for your explanation!
     
  9. sujeets

    sujeets

    Joined:
    Jul 21, 2021
    Posts:
    1
    Thanks _geo__ .You saved our day.
     
    _geo__ likes this.