Perplexing pattern( issue

I have one one line of code:
message pattern(40.5,"#")

the message shows 40, whereas I expected 41

Help please (and thanks)

message round(40.5,1)

This will round 40.5 to 41 and the message statement will show it as text even though the output is actually a value. If you need the output to be text instead of a value simply add the str( function and you donā€™t need the pattern( function at all:

str(round(40.5,1))

Shouldnā€™t pattern( round the number up to 41 ?

Donā€™t know what logic is used with the pattern( function except that 40.1 - 40.5 truncate to 40 while 40.6 - 40.9 move to 41. The round( function truncates 40.1 - 40.4 to 40 and 40.5 - 40.9 to 41. Iā€™ll leave any further explanation to someone more familiar with the subject than I am. :zipper_mouth_face:

Congratulations Larry, you have found a bug that has apparently been in Panorama for 30 years without anyone ever noticing before. I agree that one would expect that

pattern(40.5,"#")

would convert to 41, but it actually converts to 40.

Bumping the input value by even a tiny amount tips the scales, so this formula

pattern(40.500000001,"#")

does convert to 41 as expected.

This problem only occurs when rounding to an integer. This formula

pattern(40.55,"#.#")

correctly produces a result of 40.6.

Oddly, Panorama 6 has the exact same bug. This is in fact extremely odd since the source code is completely different. I guess I did a good job of making the algorithm is exactly the same even though it is in an entirely different programming language.

Until this is fixed a temporary workaround is to use the round( function, like this:

pattern(round(40.5,1),"#")

Or simply use the formula Gary suggested:

str(round(40.5,1))

I looked at the source code for the pattern( function, and it is quite complicated (this function does a lot of different things), so the problem is not obvious and probably will take significant sleuthing to track down. Iā€™ve added this to the bug report database:

I disagree.

I was taught from an early age that rounding a trailing 0.5 called for special treatment. If you always round it up, the sum of the rounded values of the set, 1.5, 2.5, 3.5, 4.5, will be 14 whereas the rounded value of their sum is 12 - a significant difference. The solution is to round up if the digit before the decimal point is odd and round down if itā€™s even. Do that with the sample above and the total of the rounded values will be 12. The underlying assumption (not always valid) is that statistically, there will be an equal distribution of odd and even preceding digits. And, if you run pattern(41.5,"#"), youā€™ll get 42 so both Panorama 6.0 and Panorama X are doing precisely what they should - there is no need to change.

And I would argue that the round( function is the one thatā€™s incorrect.

1 Like

Further testing is leading me to believe that the algorithm is designed to round the way Michael suggests. The ā€œbugā€ is not limited to integers, but to any number where the first digit to be dropped is a 5, and everything after it is a 0. In these instances the last digit retained is always even. For example

pattern(138.935,"#.##")

returns 138.94

pattern(138.945,"#.##")

also returns 138.94. Iā€™ve tried enough different numbers that I am pretty confident that it is doing this consistently. I really do believe that it was intended as a feature when it was written for Panorama 2.0, or whenever it was introduced.

Michael and Dave, thank you for your excellent input. Now that you mention it, I think I have seen that before, somewhere along the way. I have closed the bug report I just opened an hour ago, I wish they were all that easy! :slight_smile:

Actually, I think this is a feature in Appleā€™s numeric calculation package, which is used by both Panorama 6 and Panorama X. That would explain why they both work the same even though the code is completely different in completely different languages ā€“ and why they work correctly even though I didnā€™t really have a good grasp of what correctly is in this situation! Iā€™m sure some engineer at Apple researched this thoroughly at some point.

Ok, did some further research. In my code I found a link to a Unicode web page about numeric formatting, and there discovered this is called ā€œhalf-evenā€ rounding.

http://unicode.org/reports/tr35/tr35-10.html#Number_Format_Patterns

According to Wikipedia, this is one of many, many, many types of rounding available. In Wikipedia this is called ā€œRound half to evenā€

Since there are so many types of rounding, Iā€™m not sure you can call one method ā€œcorrectā€ and another ā€œincorrectā€, but half-even rounding is the default mode used by the IEEE-754 floating point standard, which is used by Apple, Microsoft, and pretty much everyone for the last 30 or so years.

Panoramaā€™s round( function does not use half-even rounding, instead it uses what Wikipedia calls ā€œround half-upā€, which Wikipedia says ā€œis widely used in many disciplinesā€ (but it also says citation needed for this assertion!).

In fact, the round( function is based on this simple calculation:

(int((number/step)+0.5))*step

Since the Panorama X documentation doesnā€™t mention any of this, itā€™s certainly understandable that Larry was perplexed. Iā€™ve gone ahead and added changes to the documentation pages for Numeric Patterns and the round( function to mention these details, with links to Wikipedia. Of course these revised pages wonā€™t be available until the next release of Panorama.

For a bug that wasnā€™t actually a bug, this has taken more effort than some actual (but very simple) bugs! :thinking: