8

I was astounded to find that the System.Numerics.Complex data type in .NET doesn't yield mathematically accurate results.

Complex.Sqrt(-1) != Complex.ImaginaryOne

Instead of (0, 1), I get (6.12303176911189E-17, 1), which looks a lot like a rounding error.

Now I realize that floating point arithmetic will lead to results like this sometimes, but usually using integers will avoid rounding errors.

Why does this seemingly basic operation yield an obviously wrong result?

Kendall Frey
  • 43,130
  • 20
  • 110
  • 148
  • 3
    The type isn't broken, no reason for the dramatics. – H H Oct 09 '12 at 19:25
  • 3
    @HenkHolterman Well, that's the best word I could find to describe it. – Kendall Frey Oct 09 '12 at 19:26
  • Possible duplicate of [Double precision problems on .NET](http://stackoverflow.com/q/566958/60761) and many others. – H H Oct 09 '12 at 19:27
  • _doesn't yield mathematically accurate results_ - that is true for all fp operators and Math.* methods for most of their input range. – H H Oct 09 '12 at 19:46
  • 1
    @HenkHolterman I know that. I know how floating point numbers work. And this is a case where it looks like it should work. – Kendall Frey Oct 09 '12 at 19:55
  • Well... wrong expectation then. I would never have trusted it. – H H Oct 09 '12 at 20:01
  • 1
    Given that Complex.Sqrt(-1) should equal Complex.ImaginaryOne, what is the suggested comparison operation if not an (in)equality check? – Triynko Oct 09 '12 at 21:56

1 Answers1

10

Look at the decompiled Sqrt method.

public static Complex Sqrt(Complex value)
{
    return Complex.FromPolarCoordinates(Math.Sqrt(value.Magnitude), value.Phase / 2.0);
}

There is in fact a rounding error caused by using polar coordinates and radians. value.Phase / 2.0 will return pi/2, which isn't an exactly representable number. When converting from polar coordinates (1, pi/2), the rounding error becomes visible when the real coordinate nears zero.

Kendall Frey
  • 43,130
  • 20
  • 110
  • 148