Bug in average() function when passing in numeric strings

It appears that there is a bug in the average() function that is not found in the min, max or sum arithmetic functions. All 4 arithmetic functions work equally well on arrays or just a comma delimited set of values. But average returns the incorrect value when you pass in string-formatted numbers, where as min, max and sum appear to cast the string values into numbers and return the correct results. I’ve confirmed this with a scenario where I input 3 different numbers into the Tools>Basic Trigger module which generates the items as strings only.

In one path I convert the strings into a numeric value with parseNumber() and the results for all four functions are correct.

In another path I leave the string-formatted values alone and I get a result for average() that is totally wrong! I’m not sure exactly what it is calculating here but sum() works fine.

With inputs of 25, 35 and 55 (parseNumber() converted strings) generate:

The average is 38.333333333333336 (right!), the minimum is 25,the max is 55 and the sum is 115.

But inputs of “25”, "35 and “55” generates:

The average is 84518.33333333333 (WRONG!), the minimum is 25,the max is 55 and the sum is 115.

Can someone confirm this for me and I can submit the Make bug formally. Here’s the sample scenario – make sure each value in the basic trigger is unique.

average() computation bug for string-formatted numbers.json (16.5 KB)

Also the UI help is incorrect for average(), as arrays are allowed as inputs.

@samliew would like to have your eyes on this to confirm what I’m seeing.

Output

Screenshot_2024-04-30_090424

If in doubt, always use parseNumber first before putting them in math functions.

Module Export

You can copy and paste this module export into your scenario. This will paste the modules shown in my screenshots above.

  1. Copy the JSON code below by clicking the copy button when you mouseover the top-right of the code block
    Screenshot_2024-01-17_200117

  2. Enter your scenario editor. Press ESC to close any dialogs. Press CTRLV (paste keyboard shortcut for Windows) to paste directly in the canvas.

  3. Click on each imported module and save it for validation. You may be prompted to remap some variables and connections.

View Module Export Code

JSON

{
    "subflows": [
        {
            "flow": [
                {
                    "id": 105,
                    "module": "util:SetVariables",
                    "version": 1,
                    "parameters": {},
                    "mapper": {
                        "variables": [
                            {
                                "name": "average",
                                "value": "{{average(25; 35; 55)}}"
                            },
                            {
                                "name": "average numeric int strings",
                                "value": "{{average(emptystring + 25; emptystring + 35; emptystring + 55)}}"
                            },
                            {
                                "name": "average numeric dec strings",
                                "value": "{{average(emptystring + 25.12; emptystring + 35.12; emptystring + 55.12)}}"
                            }
                        ],
                        "scope": "roundtrip"
                    },
                    "metadata": {
                        "designer": {
                            "x": 1535,
                            "y": -990
                        },
                        "restore": {
                            "expect": {
                                "variables": {
                                    "items": [
                                        null,
                                        null,
                                        null
                                    ]
                                },
                                "scope": {
                                    "label": "One cycle"
                                }
                            }
                        },
                        "expect": [
                            {
                                "name": "variables",
                                "type": "array",
                                "label": "Variables",
                                "spec": [
                                    {
                                        "name": "name",
                                        "label": "Variable name",
                                        "type": "text",
                                        "required": true
                                    },
                                    {
                                        "name": "value",
                                        "label": "Variable value",
                                        "type": "any"
                                    }
                                ]
                            },
                            {
                                "name": "scope",
                                "type": "select",
                                "label": "Variable lifetime",
                                "required": true,
                                "validate": {
                                    "enum": [
                                        "roundtrip",
                                        "execution"
                                    ]
                                }
                            }
                        ],
                        "interface": [
                            {
                                "name": "average",
                                "label": "average",
                                "type": "any"
                            },
                            {
                                "name": "average numeric int strings",
                                "label": "average numeric int strings",
                                "type": "any"
                            },
                            {
                                "name": "average numeric dec strings",
                                "label": "average numeric dec strings",
                                "type": "any"
                            }
                        ]
                    }
                }
            ]
        }
    ],
    "metadata": {
        "version": 1
    }
}

Ok so you’ve confirmed it. The sum() function does not appear to care whether the values are strings or numeric so that’s inconsistent.

There should not be any inconsistency here. These functions either should accept strings as numbers or just accept numbers and throw an error if the values aren’t numbers. This could lead to some unexpected behaviour especially for new users who expect this to work and get values but the values are wrong. I rarely use parseNumber unless I know I need to deal with numbers and I think this is a bug and average() should be fixed to accept strings that have numbers in them.

2 Likes

I checked this with decimal values as well – the sum() function works fine when passing in string-formatted decimal numbers, where as average() returns NaN rather than an incorrect average value.

I posted this as a ticket to Make support as ticket # 1010024

Update: Make recommends using parseNumber() to ensure all inputs to average() are numeric. Since there is no built in average() function in JavaScript, make must have implemented average() without regard to string input and as a result it’s somewhat deficient in this regard. The sum() function probably works due to its internal implementation since JavaScript doesn’t have a built in sum() function either.

2 Likes