Why the result is different?

Code:

8 ENTER

0 COMPLEX

8 i0

+/-

-8 i0

3 1/X

3.33333333333ᴇ-1 ***

Y↑X

1 -i1.73205080757

Code:

-8 ENTER

0 COMPLEX

-8 i0

3 1/X

3.33333333333ᴇ-1 ***

Y↑X

1 i1.73205080757

In the first case, the imaginary part is -0, while in the second case, it is 0.

-0, also known as signed zero, is a feature of IEEE-754 floating point. The difference between 0 and -0 shouldn't matter in Free42, but apparently this is a case where it does and where there is no special-case code for zero to prevent this behavior.

What happens internally is that the number is first converted to polar using the hypot() and atan2() functions, and atan2(-0, -8) => -pi, while atan2(0, -8) => pi. After multiplying that angle by 1/3, you end up on opposite sides of the real axis.

I'll fix this in the next release.

(You won't see this behavior in ->POL, because it does contain special-case code for handling zero in either coordinate.)

From a numerical viewpoint, the current behaviour is correct.

(02-24-2021 02:02 AM)Thomas Okken Wrote: [ -> ]In the first case, the imaginary part is -0, while in the second case, it is 0.

-0, also known as signed zero, is a feature of IEEE-754 floating point. The difference between 0 and -0 shouldn't matter in Free42, but apparently this is a case where it does and where there is no special-case code for zero to prevent this behavior.

Thank you for explaining.

(02-24-2021 02:52 AM)Paul Dale Wrote: [ -> ]From a numerical viewpoint, the current behaviour is correct.

I don't think so. -8, -8+0i and -8-0i it's still the same number and the principal cube root should be the same too.

Anyway, in such cases it's better to emulate HP-42s behavior, and it always returns "1.0000 i1.7321" here.

The 1984 HP-71 was supporting the signed zero, but it was sometimes a source of confusion for users and the signed zero was not kept in later machines (starting with the 28C).

So yes, the HP-71, with the Math ROM, gives the same (correct) results:

> (-8,0) ^ (1/3)

(1,1.73205080757)

> (-(8,0)) ^ (1/3)

(1,-1.73205080757)

J-F

Yes, the sign of zero is important!

Read Kahan's 'How Java’s Floating-Point Hurts Everyone Everywhere'.

Please, leave it as it is - Free42 would be one of the only ones to get it right ;-)

Werner

(02-24-2021 02:02 AM)Thomas Okken Wrote: [ -> ]atan2(-0, -8) => -pi, while atan2(0, -8) => pi

-pi < arg(z) ≤ pi

Since polar form and rectangular form should match, I think -8 ± 0i should be adjusted to -8 + 0i = 8 exp(i*pi)

For the same reason, sqrt(-4 - 0i) = sqrt(-4 + 0i) = 2i

4 [ENTER] 0 [COMPLEX] [+/-] [SQRT] → 2i

(02-24-2021 08:59 AM)Werner Wrote: [ -> ]Please, leave it as it is - Free42 would be one of the only ones to get it right ;-)

There is that! But the HP-42S doesn't support -0, and when I did the review of complex transcendentals a few years ago, I added special cases for pure-real and pure-imaginary numbers that made the not-42S-compatible behavior with -0 disappear.

That review only covered the transcendentals, though. I missed SQRT, for which I ended up creating a special case for pure-imaginary a bit later. And this issue with Y^X follows the same pattern.

(02-24-2021 01:35 PM)Thomas Okken Wrote: [ -> ] (02-24-2021 08:59 AM)Werner Wrote: [ -> ]Please, leave it as it is - Free42 would be one of the only ones to get it right ;-)

There is that! But the HP-42S doesn't support -0 ...

Hi, Thomas Okken

Can you elaborate what is decided ?

If Free42 do support -0, then sqrt(-4-0i) = sqrt(4*exp(-pi*i)) = 2*exp(-pi/2*i) = -2i

But, user need to know "-0" is actually inputed.

-0 should displayed as "-0", not "0"

-4-0*i should displayed as "-4 -i0", not "-4 i0"

If not, (-8-0i)^(1/3) = (-8+0i)^(1/3) = 1 + sqrt(3)*i

(02-24-2021 02:47 PM)Albert Chan Wrote: [ -> ]Can you elaborate what is decided ?

The behavior reported by Ajaja is a bug. Free42 does not support -0, and so the two calculations he showed should return the same result.

The only case where the sign of zero actually matters in Free42 is when it gets passed as the first parameter to atan2(). That scenario is supposed to be prevented by special-case logic, but that check is missing in Y^X. I'll fix that in the next release.

.. and, not unimportant, that way it is consistent with the 42S.

Werner

FYI, we can remove -0 parts of x, by doing

x-x+x = 0+x
(assumed 0+x does not get optimized away, to plain x)

Redo OP example:

8 [Enter] 0 [Complex] [+/-] → x = -8 - 0i

[Enter] - [LastX] + → x-x+x = -8 + 0i

3 [1/x] [y^x] → ≈ 1 + 1.73205080757*i