Załóżmy, że na dwóch komputerach odpalamy dwie identyczne deterministyczne symulacje. Zgodnie z logiką, po minucie, po godzinie i po dwóch dniach stan na obu maszynach powinien być taki sam. Niestety, logika tutaj zawodzi. Po dwóch dniach będziemy mieli całkiem inne rezultaty, a najprawdopodobniej obliczenia rozjadą się już po kilku sekundach. Czemu? To wina niedokładności operacji zmiennoprzecinkowych (dla komputera 0.1 + 0.2 = 0.30000000000000004) i różnych ich implementacji na różnych architekturach.

Stworzenie w pełni deterministycznego programu to nie trywialne zadanie: wyniki mogą być różne w zależności od procesora, kompilatora, ustawień kompilacji i faz księżyca. Programiści JavaScriptu mają tutaj na szczęście trochę łatwiej, bo ECMA wprowadziła jeden standard, którego muszą trzymać się wszystkie przeglądarki.

The Number type has exactly 18437736874454810627 (that is, 264−253+3) values, representing the double-precision 64-bit format IEEE 754 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic

Chociaż cały czas nie możemy zaufać JSowi, że dwie symulacje na dwóch komputerach dadzą takie same wyniki, to rozbieżności powinny być nie duże. „Nie duże”, czyli jakie konkretnie? Przy tworzeniu modułu sieciowego do prostej gry musiałem się upewnić, że logika odpalona niezależnie na serwerze i kliencie nie rozjedzie się za szybko. Machnąłem szybki tekst wykonujący miliard działań i podesłałem go znajomym (wszystkie większe przeglądarki oprócz Safari + różne architektury, w tym Mac). Jakie wyniki?

 

Próba
Test 2
Test 1
100
0%
0%
100000
-0,0000006576%
-0,00000000000254%
5000000
-0,00022%
0,00000000013%
10000000
-0,00163%
0,00000000001779%

Tabelka pokazuje rozstęp, czyli różnicę między najniższą i najwyższą wartością danych, podzielony przez największą wartość. W skrócie: po miliardzie iteracji, wynik na dwóch dowolnych przeglądarkach nie powinien różnić się bardziej, niż o ~0,00163%. Czy to dużo, czy mało – zależy od naszych potrzeb. Dla mnie różnica była na tyle mała, ze nie bałem się odpalić dwóch niezależnych symulacji na serwerze/kliencie.

W ramach ciekawostki: w wynikach dało się wyróżnić dwie grupy.
  1. Opera i Chrome z identycznymi wynikami  za sprawą V8, które obsługuje JSa w obu przeglądarkach
  2. Firefox i IE z bardzo podobnymi wynikami, chociaż pod maską siedzą dwa różne silniki: SpiderMonkey i Chakra (Edge, którego też napędza Chakra, dla odmiany dał całkiem inne wyniki)
  • Did you like it?
  • Yes   No