"08".toNumber() = 0

Converting the string "08" or "09" with toNumber function, both produces the integer value 0 on a Forerunner 920XT with lastest firmware.

In the simulator the result is as expected ("08".toNumber() = 8 and "09".toNumber() = 9).

Not sure if this is a Monkey C language feature :-)

Code snippet and output:

for (var i = 0; i < 10; i++) {
var strI = i.toString();
var intI = strI.toNumber();
var dblI = intI.toDouble();

Sys.println("i: " + i + ", strI: " + strI + ", intI: " + intI + ", dblI: " + dblI);

strI = "0" + i.toString();
intI = strI.toNumber();
dblI = intI.toDouble();

Sys.println("i: " + i + ", strI: " + strI + ", intI: " + intI + ", dblI: " + dblI);
}

i: 0, strI: 0, intI: 0, dblI: 0.000000
i: 0, strI: 00, intI: 0, dblI: 0.000000
i: 1, strI: 1, intI: 1, dblI: 1.000000
i: 1, strI: 01, intI: 1, dblI: 1.000000
i: 2, strI: 2, intI: 2, dblI: 2.000000
i: 2, strI: 02, intI: 2, dblI: 2.000000
i: 3, strI: 3, intI: 3, dblI: 3.000000
i: 3, strI: 03, intI: 3, dblI: 3.000000
i: 4, strI: 4, intI: 4, dblI: 4.000000
i: 4, strI: 04, intI: 4, dblI: 4.000000
i: 5, strI: 5, intI: 5, dblI: 5.000000
i: 5, strI: 05, intI: 5, dblI: 5.000000
i: 6, strI: 6, intI: 6, dblI: 6.000000
i: 6, strI: 06, intI: 6, dblI: 6.000000
i: 7, strI: 7, intI: 7, dblI: 7.000000
i: 7, strI: 07, intI: 7, dblI: 7.000000
i: 8, strI: 8, intI: 8, dblI: 8.000000
i: 8, strI: 08, intI: 0, dblI: 0.000000
i: 9, strI: 9, intI: 9, dblI: 9.000000
i: 9, strI: 09, intI: 0, dblI: 0.000000
  • Looks like it might be a problem with the 920 FW.. (maybe other devices?)

    Here's what's happening:

    with the leading zero, "08" and "09" are considered to be in Octal on the watch (00-07 are valid octal numbers, and show correctly with a toNumber() ), but as an octal number, "08" and "09" are not valid and result in 0.

    The easiest thing to do is just strip the leading zeros from the string before you do a toNumber() on it, as you can do that today if it is a FW problem that could take time to fix.
  • This bug was address in 2.x devices already, but the change was not integrated into 1.x devices like the 920XT. I'm checking to see whether we have plans to bring it into 1.x devices, too.

    UPDATE: This was supposed to already have been addressed on 1.x devices, but apparently we still have a bug somewhere. :) I've opened a new ticket to investigate the issue.
  • Converting the string "08" or "09" with toNumber function, both produces the integer value 0 on a Forerunner 920XT with lastest firmware.

    This is as expected.

    "08" and "09" are considered to be in Octal on the watch (00-07 are valid octal numbers, and show correctly with a toNumber() ), but as an octal number, "08" and "09" are not valid and result in 0.

    Yes. This is the issue.

    The easiest thing to do is just strip the leading zeros from the string before you do a toNumber() on it

    No, that is probably not the right solution. The method String.toNumberWithBase() was added to allow users to specify the base to use when parsing numbers, as opposed to assuming a base given a prefix.

    This bug was address in 2.x devices already, but the change was not integrated into 1.x devices like the 920XT. I'm checking to see whether we have plans to bring it into 1.x devices, too.

    I'm not sure what is going on in Garmin land, but issues relating to the parsing of octal numbers have come up before. See these threads...

    https://forums.garmin.com/showthread.php?341494
    https://forums.garmin.com/showthread.php?339493

    The toNumberWithBase() method was added to solve this problem, so I'm not sure what there is to fix. Unless, of course, your making the function throw an exception when an illegal character is found.

    Travis
  • Of course, if the simulator behaves differently than the device a fix should be made, but it seems to me that the simulator is in error in this case.
  • Travis - with toNumberWithBase, the SDK API 2.2.1 doc has:
    #toNumberWithBase(base) &#8658; Number

    Convert a string to a number using the specified base.
    Since:
    1.4.1


    The "Since" part... Isn't the 920 on 1.3.x or is it a typo in the doc?
  • You are absolutely right. I thought that the fr920xt was at 1.4, but it is 1.3.4... In that case, your fix or an implementation of a base 10 toNumber() is the right thing to do.

    That said, I don't understand what fix Garmin would be making to toNumber(). As far as I can tell, it is behaving correctly.

    Travis
  • Just tested C# and Pascal:
    http://volatileread.com/UtilityLibrary/SnippetCompiler
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public class Program
    {
    public static void Main()
    {
    int numVal = Int32.Parse("08");
    Console.WriteLine(numVal);
    Console.WriteLine("Hello C#");
    }
    }

    Result is 8

    The same is for
    procedure TForm1.Button5Click(Sender: TObject);
    Var
    I:Integer;
    begin
    I:=StrToInt('08');
    Writelog(Format('%d', ));
    end;[/CODE]

    Expected value is 8.
    Accordind to that documentaion:
    #toNumber &#8658; Number
    If a string is in a base 10 numeric form, e.g., &#8220;123&#8221; or &#8220;08&#8221;, convert it to a Number object with toNumber().
    Returns:
    (Number) &#8212; A Number object, or error
    Since:
    1.0.0

    So, Travis, it must be corrected and it is definitely a bug.

    NB/ Poor epix, if it has this issue, it will be never fixed.
  • Former Member
    Former Member over 8 years ago
    Originally the toNumber() function for the String class was implemented to match the functionality of the C method strtol with a base of 0. The documentation indicated that this method would automatically convert decimal strings (e.g. "1234") and hex string (e.g. "0x1234") to integers. This was working "as designed", but the Octal behavior is not something that was documented.

    We decided that the Octal behavior was not desired, and modified the functionality of String.toNumber() to behave in line with C strtol with a base of 10, and updated the documentation to reflect this change. Because some developers may have been taking advantage of the automatic base detection, we also added the String.toNumberWithBase() method that can replicate the removed String.toNumber() behavior.

    We initially only brought this change to the 2.x release, but later brought it to the 1.x releases as well. As has been noted, this was brought into at 1.4.1, so the change will not be reflected in products until they integrate that release.
  • Just tested C# and Pascal:

    Yes, but MonkeyC is not based on C# or Pascal.

    Originally the toNumber() function for the String class was implemented to match the functionality of the C method strtol with a base of 0.

    Yes, this is consistent with my memory. I don't believe (but I could check) that toNumber() was documented to behave like strtol(..., ..., 0), but it did behave that way.

    We decided that the Octal behavior was not desired, and modified the functionality of String.toNumber() to behave in line with C strtol with a base of 10, and updated the documentation to reflect this change.

    ... So it's a flap forty forty forty flip flop and a flap fee....

    So this change 'fixed' the undocumented behavior for strings with a leading zero, but broke the documented behavior for strings with a leading '0x' or '0X'?

    Because some developers may have been taking advantage of the automatic base detection, we also added the String.toNumberWithBase() method that can replicate the removed String.toNumber() behavior.

    Honestly, I'm surprised that the a breaking change in behavior for toNumber() was allowed outside of a major release. It is my understanding that such a change would cause a shipped application to behave differently depending on the firmware version in use on a device.

    Travis
  • mc has had some "c" like conventions all along (leading 0, 0x, etc), as well as things the string used by .format(). (c, not c++ or c#)

    As a long time "c" guy, it didn't bother me. But then again, I once balanced by checkbook using hex math..... :)