Ticket Created
over 3 years ago

CIQQA-1396

Bug: Print doubles with full precision to prevent weird behaviour by test messages.

    (:test)
    function garminDouble(logger) {
      var mile = 0.6213711922d;
      var km = 21.0975;

      var hm = mile * km;

      Test.assertEqualMessage(hm, 13.109379d,
        Lang.format("half marathon in miles $1$ equals to $2$",
          [ hm, 13.109379d ]));
    }

The following code fails with: Exception: ASSERTION FAILED: half marathon in miles 13.109379 equals to 13.109379

Please make sure that the printed version equals what the actual test uses for the precision of the double. As soon as you toString() the values, it becomes the same value. Which is unclear and very confusing.

  • "What do you get for hm.equals(13...)?"

    Why don't you try it, since you don't believe what people are trying to tell you?

    var mi = 0.6213711922d * 21.0975d;
    System.println(mi); // 13.109379
    System.println(mi.equals(13.109379d)); // false
    System.println(mi == 13.109379d);  // false
    System.println(mi.format("%.17g")); // 13.1093787274395
    System.println(mi.equals(13.1093787274395d)); // true
    System.println(mi == 13.1093787274395d); // true
    The fact that Long and Double are complex objects in Monkey C (as opposed to simple objects like Number and Float) affects their memory consumption, but doesn't affect the fact that you can use == to compare them. Why this isn't also supported for String is just one of those things we'll never know.... (I'm guessing it's because Monkey C wants to be Java-ish even though it doesn't really have primitives like Java, and even its "simple objects" don't fully correspond to the Java primitives, as Long and Double aren't simple objects yet they support comparison via "=="). (C# is just fine with comparing 2 strings via "==")
  • What do you get for hm.equals(13...)?

  • "The real question is what should be expected when a double is printed out "directly", using Lang.format or System.println."

    Or to be more precise, "what should be expected when you call Float.toString() or Double.toString()?"

    Seems that in most languages, you get all the decimal places, but not in Monkey C.

  • Having said all that, I kinda get why Monkey C does this. It's probably because an assumption is made that you're going to output stuff to a tiny screen (like the screen of a watch), so in that case it makes sense to only display a limited number of decimals.

    It doesn't make sense for stuff that's logged to the console, though.

  • "Can you try comparing with hm.equals(13....)?"

    , as discussed in the other thread, that's not the problem. The perceived problem is that only 6 digits are printed out but the true value has many more significant decimal places.

    Once again, "==" works fine to compare doubles (and longs).

    *However*, even in C, using printf("%g") on "21.0975d * 0.6213711922d" only prints out 4 places, and using "%f" on the same value prints out 6 places.

    The real question is what should be expected when a double is printed out "directly", using Lang.format or System.println.

    If you use alert or console.log in javascript, you get full precision. Same with print() in python. Same with C# and Java. So it looks like precedent is not on the side of Monkey C.

    e.g. python:

    >>> x = 21.0975 * 0.6213711922
    >>> print (x)
    13.1093787274395
    >>> print (x == 13.1093787274395)
    True

    In this case, the workaround is to force more decimals to be printed out.

    e.g.

    Test.assertEqualMessage(hm, 13.109379d,
            Lang.format("half marathon in miles $1$ equals to $2$",
              [ hm,format("%.17g"), 13.109379d.format("%.17g") ]));

    (See: https://stackoverflow.com/a/21162120)

    This should produce output that makes more sense. e.g.

    ASSERTION FAILED: half marathon in miles 13.109378632625781 equals to 13.109379000000001