Един ден има 500654080 микросекунди

Знаем, че един ден има 24 часа. Един час има 60 минути. Една минута има 60 секунди. Една секунда има 1000 милисекунди. Една милисекунда има 1000 микросекунди. Колко микросекунди има един ден?

Ще направим решението на тази задача като умножим всички мисла от по-горе със следната програма на Java:

 long microseconds_per_day = 24 * 60 * 60 * 1000 * 1000;
 System.out.println(microseconds_per_day);

Изненадващо изходът e 500654080, а не 86400000000. Защо се получи така?

Софизмът в тази задача се получава от прехвърляне на типа данни, но по особен начин. Всъщност long побира и по-големи числа от очакваното – типът е 8 байтов, т.е. побира числа в интервала от -9223372036854775808 до 9223372036854775807, т.е. значително много по-големи от търсения резултат. Проблемът идва от там, че всички числа вдясно от равенството не са long, а са int, а от там целият израз се пресмята до тип int и впоследствие се преобразува в long, когато се извършва присвояването. Типът int е 4 байтов и побира числа в интервала от -2147483648 до 2147483647, тоест недостатъчно големи за числото, което ни е нужно. Когато се получи препълване на типа, Java “превърта” числото от максималното възможно към минималното (т.е. в света на Java и повечето други езици за програмиране 2 147 483 647 + 1 = -2 147 483 648). В случая при извършване на последното умножение имаме многократно “превъртане” до достигане до получения грешен резултат.

Решението на този софизъм е да укажем експлицитно в дясната част на равенството, че желаем да работим с числа от тип long:

 long microseconds_per_day = 24L * 60 * 60 * 1000 * 1000;
 System.out.println(microseconds_per_day);

Един вариант на тази задача, в който не се появяват толкова големи числа на екрана, е следния: Ако знаете, че един ден има 24*60*60*1000*1000  микросекунди и също така един ден има 24*60*60*1000 = 86400000 милисекунди, то изчислете колко микросекунди има една милисекунда? Софизмът се демонстрира със следния пример (по-прикрита за учениците грешка – в този случай ако не я видят веднага, може да им се даде допълнителна задача да проверят дали резултата е верен с помощта на търсачка в интернет):

 long microseconds_per_day = 24*60*60*1000*1000;
 long milliseconds_per_day = 86400000;
 System.out.println(microseconds_per_day / milliseconds_per_day);

или с (по-очевидна грешка – веднага се забелязва, че отговорът ще е грешен):

 long microseconds_per_day = 24*60*60*1000*1000;
 long milliseconds_per_day = 24*60*60*1000;
 System.out.println(microseconds_per_day / milliseconds_per_day);

Резултатът и в двата случая ще е 5, а не очакваното 1000.

Leave a Reply

Your email address will not be published. Required fields are marked *