Acknowledged

Cannot Calculate Mod (%) with Doubles

I get an error when I try to calculate a mod with two doubles. There is no error when doing the equivalent calculation with a formula.

var a = 5 as Double;  // or 5d
var b = 2 as Double;  // or 2d
var c = a % b;  // ERROR: Cannot perform operation 'mod' on types '$.Toybox.Lang.Double' and '$.Toybox.Lang.Double'.
var d = a - (Math.floor(a/b)) * b;  // No error

Environment:

Mac OS Sequoia 15.1.1 (24B2091)

Connect IQ SDK 7.4.3

Monkey C Extension 1.1.0

VS Code 1.96.4

----------

EDIT: It appears that it's normal for the mod operator to not work with doubles. I would like to recommend mentioning this in the Reference Guide Arithmetic Operators section along with any other exceptions.

Parents
  • Yeah, as you've discovered, in Monkey C, mod is only defined for integers (like C), and not also for floating-point types (like Java). I doubt this will change, so your only workaround is to define a helper function with a formula to calculate mod, as in your example.

    One note about your code:

    var a = 5 as Double;
    var b = 2 as Double;

    The type casts "a = 5 as Double" and "b = 2 as Double" don't actually change 5 and 2 into Doubles, they only tell the type checker that those values are Doubles.

    If you remove the type casts, "var c = a % b;" will work fine at runtime (as you may have noticed), since a and b are actually Numbers at runtime, despite the type casts to the contrary.

    The way to actually make those values into Doubles to use the "d" suffix:

    var a = 5d;
    var b = 2d;

    They way to signify that a value is a Float is to either use the "f" suffix and/or include a decimal point.

    var a = 5f;
    var b = 2f;

    or

    var a = 5.0;
    var b = 2.0;

    (The corresponding suffix for Long is "l" - lowercase L).

    If you use any of the above ways to make 5 and 2 into floats/doubles, you will see that a % b will also crash at runtime.

    Imo it's best to avoid unnecessary type casts where possible, as they can be misleading, and at worst, they can lead to runtime errors. For example, the following code would build without errors, but it would crash at runtime:

    var a = 5.0 as Number;
    var b = 2.0 as Number;
    var c = a % b;

Comment
  • Yeah, as you've discovered, in Monkey C, mod is only defined for integers (like C), and not also for floating-point types (like Java). I doubt this will change, so your only workaround is to define a helper function with a formula to calculate mod, as in your example.

    One note about your code:

    var a = 5 as Double;
    var b = 2 as Double;

    The type casts "a = 5 as Double" and "b = 2 as Double" don't actually change 5 and 2 into Doubles, they only tell the type checker that those values are Doubles.

    If you remove the type casts, "var c = a % b;" will work fine at runtime (as you may have noticed), since a and b are actually Numbers at runtime, despite the type casts to the contrary.

    The way to actually make those values into Doubles to use the "d" suffix:

    var a = 5d;
    var b = 2d;

    They way to signify that a value is a Float is to either use the "f" suffix and/or include a decimal point.

    var a = 5f;
    var b = 2f;

    or

    var a = 5.0;
    var b = 2.0;

    (The corresponding suffix for Long is "l" - lowercase L).

    If you use any of the above ways to make 5 and 2 into floats/doubles, you will see that a % b will also crash at runtime.

    Imo it's best to avoid unnecessary type casts where possible, as they can be misleading, and at worst, they can lead to runtime errors. For example, the following code would build without errors, but it would crash at runtime:

    var a = 5.0 as Number;
    var b = 2.0 as Number;
    var c = a % b;

Children
No Data