07-14-2018, 10:52 PM

While testing some RPL code recently, I was reminded of a problem that can occur on the 50g when attempting to test lists for equality. Here's an example of how the problem can show up:

1) Set your 50g to exact mode

2) Enter the list { 1 2 3 } on the stack

3) Press ENTER to make a duplicate, then 2 * to double each list element

4) Press 2 / to divide each element in the second list by 2

At this point, you should have what appears to be two identical lists in stack levels 1 and 2:

2: { 1 2 3 }

1: { 1 2 3 }

Execute SAME (or ==) to compare the two lists for equality. I'm of the opinion that most rational people would expect a result of 1, but unfortunately my rev 2.15 50g sees those lists as not being the same. The reason for this is a bit complicated, and even worse, it's not as predictable as you might imagine. Try the same test as above, but this time use { 10 20 30 } as the initial list. Surprise! Unlike before, those lists are the same. Likewise, try multiplying or dividing by 1 instead of 2. What result do you think that will give?

What's the difference, and why does this happen? The answer to that is a bit complicated, and has to do with the following:

The 50g is far more consistent with its handling of approximate numbers, so this isn't usually a problem with those values. I've yet to find a way to cause a similar problem with approximate numbers.

I'm curious as to whether others have run into this issue, and if so, how you dealt with it. The only UserRPL methods I can think of are very slow as list sizes increase (eg. applying →STR STR→ to the lists before comparing). What methods have you found to deal with this?

Note that this is really just an issue for the 48gII/49g+/50g, as earlier RPL models either don't use exact integers or treat them differently when performing math operations on lists of them. On my rev. 1.19-6 49G, { 1 2 3 } 2 * strangely yields a result of { 2. 4. 6. }, regardless of mode.

1) Set your 50g to exact mode

2) Enter the list { 1 2 3 } on the stack

3) Press ENTER to make a duplicate, then 2 * to double each list element

4) Press 2 / to divide each element in the second list by 2

At this point, you should have what appears to be two identical lists in stack levels 1 and 2:

2: { 1 2 3 }

1: { 1 2 3 }

Execute SAME (or ==) to compare the two lists for equality. I'm of the opinion that most rational people would expect a result of 1, but unfortunately my rev 2.15 50g sees those lists as not being the same. The reason for this is a bit complicated, and even worse, it's not as predictable as you might imagine. Try the same test as above, but this time use { 10 20 30 } as the initial list. Surprise! Unlike before, those lists are the same. Likewise, try multiplying or dividing by 1 instead of 2. What result do you think that will give?

What's the difference, and why does this happen? The answer to that is a bit complicated, and has to do with the following:

- How the built-in RPL compiler substitutes whole numbers in the range -9..9 with a reference to a ROM-based constant instead of a raw value when it is invoked
- How SAME/== only looks at the binary data of the whole list (instead of individual elements) when comparing for equality
- How mathematical operations involving exact integers sometimes result in raw values, and sometimes don't

The 50g is far more consistent with its handling of approximate numbers, so this isn't usually a problem with those values. I've yet to find a way to cause a similar problem with approximate numbers.

I'm curious as to whether others have run into this issue, and if so, how you dealt with it. The only UserRPL methods I can think of are very slow as list sizes increase (eg. applying →STR STR→ to the lists before comparing). What methods have you found to deal with this?

Note that this is really just an issue for the 48gII/49g+/50g, as earlier RPL models either don't use exact integers or treat them differently when performing math operations on lists of them. On my rev. 1.19-6 49G, { 1 2 3 } 2 * strangely yields a result of { 2. 4. 6. }, regardless of mode.