Complex Numbers -- stack overflow in tests; floating point errors

Hi,

the typescript template in the “Complex Numbers” challenge has a bunch of getters that return more complex numbers; like in this simplified example:

class Complex {
   get conj () { return new Complex(this.real, -this.imag); }
}

This is a problem in jest tests. When a test case fails, jest will try to walk the object that didn’t match the expectation, so it can print it. But when inspecting the property conj it’ll see another Complex number, which jest will want to print too; of course that object has another conj property that returns another Complex… and so on.

This means that all failing tests will run into a stack overflow.

In general I think getters are overused in these challenges so imho the best solution would be to turn all those getters into methods instead.

Another solution would be to not write tests like expect(complex1).toEqual(complex2) beause jest does odd things there, and instead only compare the real and imag parts.

(The test case for conj is especially funny. It checks 5+0i is turned into 5+0i but if you just use the implementation I provided in the example above then the test will stack overflow because positive 0 is different from negative 0 and jest goes into “walk entire object” mode. +0 vs -0 is an oddity of IEEE 754 floating point numbers I’ve known about but I haven’t really ever encountered it being a problem in javascript before.)


Also, the test that checks for complex division (xit("Divide numbers with real and imaginary part")) checks for an exact match, when it should be using expect(...).toBeCloseTo or something similar to avoid floating point weirdness.

2 Likes

This is because the .toEqual uses Object.is for its deep equality test

Object.is(0, -0) is false

However 0 === -0

So you should do

new ComplexNumber(this.real, this.imag === 0 ? this.imag: - this.imag)

1 Like

Ah. You know what, this may also be an issue in the JavaScript track.
Can you or @Flonk test that? I would test it myself but I am on an experimental in-browser test runner.

I do think we should fix the tests here to not break on trying to compare the things either by using a different matcher or a custom one.

I don’t think toBeCloseTo is the issue here, given what @backdevjung posted.