0
export class AppService {
  calculatePrice(books: Book[]): number {
    // The idea is to group a sets of books together
    if (books.length === 0) return 0;
    if (books.length === 1) return PRICE;

    const flatBooks = books.flat(2);
    const setOfBooks = [...new Set(flatBooks)];

    const cumulate = PRICE * setOfBooks.length * DISCOUNT[setOfBooks.length];
    // remove elements
    for (const book of setOfBooks) {
      const index = flatBooks.indexOf(book);
      flatBooks.splice(index, 1);
    }

    console.log(cumulate);

    return cumulate + this.calculatePrice(flatBooks);
  }
}

Well, I made a tests for a recursive function, but I got a strange case.
Instead of having 184.4€ for a test of a group of books, I got 184.39999999999999998
I used an addition and a multiplication, so it's impossible to get this price All details are below

https://github.com/wajdibenabdallah/liberation-kata

Just make clone then pnpm i then pnpm t

  • 1
    https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Dave Newton Sep 01 '23 at 17:10
  • Use [`expect(...).toBeCloseTo()`](https://jestjs.io/docs/expect#tobeclosetonumber-numdigits) since floating point math tends to be inaccurate like that (as VLAZ's linked answer says). – AKX Sep 01 '23 at 17:13

1 Answers1

0

Since floating point math is inaccurate, you'll want to use the toBeCloseTo Jest matcher.

IOW, in your tests where you're currently doing e.g.

expect(appController.calculatePrice(booksExample1)).toBe(PRICE);

you can do

expect(appController.calculatePrice(booksExample1)).toBeCloseTo(PRICE);

if you don't want to switch to precise decimals (e.g. with decimal.js).

AKX
  • 152,115
  • 15
  • 115
  • 172
  • Thank you, i didn't know this : Using exact equality with floating point numbers is a bad idea Floating point numbers are always subject to round off errors. Instead you should check if they're within some small range (like, smallRange = 0.00001 ) of each other. – Wajdi Ben Abdallah Sep 01 '23 at 17:30