Ground Round
Dziś zagadka „matematyczna” 🙂
- Jak często poniższy kod wypisze Ground Round?
import java.util.*; public class UrlSet { public static void main(String[] args) { Random rnd = new Random(); int i = rnd.nextInt(); if (Math.round(i) != i) { System.out.println("Ground Round"); } } }
Odpowiedzi:
(a) Nigdy
(b) Rzadko
(c) Prawie przy każdym uruchomieniu
(d) Przy każdym uruchomieniu
- Odpowiedź uzasadnij i wyjaśnij dlaczego tak to działa
- Jak poprawić powyższy kod, aby zachowywał się zgodnie z intuicją
Autorami zagadki są Joshua Bloch i William Pugh
Odpowiedz: (c), a dokładnie 2^32 – 2^23 razy na 2^32 wywołań program pokaże napis „Ground Round”, czyli prawie zawsze
Uzasadnienie: Zmienne typu integer wykorzystują 32 bity na reprezentację wartości. Zmienne typu float mają podstawę 23 bitową, dlatego mogą przechować wartości ze zbioru int nie większe niż 2^23 (oczywiście wartości większe niż 2^23 mogą przechowywać ale tylko i wyłącznie ze stratą prezycji)
Wywołanie Math.round(i) przeprowadzi niejawną konwersję int do float co dla integerów większych niż 2^23 spowoduje spadek prezycji i warunek porównania nie zostanie spełniony.
Aby program działał zgodnie z intuicją należy użyć większej precyzji dla operacji zmiennoprzecinkowych (czyli np zrzutować int na double przy wywołaniu metody Math.round(i))