* Кутия цигари
Публикувано на 17 юли 2009 в раздел Математика.
Попаднах на интересна статия от сайта Consumerist. Преди два-три дни в американската преса гръмна забавна новина. Американецът Джон Мужински отишъл да си купи цигари. Платил с кредитната си карта VISA, взел касовата си бележка и тръгнал по работа.
След малко обаче погледнал бележката и останал като гръмнат - оказало се, че са му взели 23 квадрилиона долара. Точната сума всъщност била $23 148 855 308 184 500.00. Естествено ставало дума за програмна грешка - системата на VISA се била "бъгнала".
Няколко часа отнели на Джон докато оправи бъкиите си с банката. В крайна сметка всичко завършило благополучно и дори таксата от 20 долара за прехвърляне на лимита му била опростена.
Интересно е да се разровим по-дълбоко в случая. Защо се е получила точно тази сума? Изглежда достатъчно произволна, нали?
Първото предположение, че става дума за зимбабвийски долари, естествено се оказало грешно:
Отговорът на загадката се крие в преобразуване на числото от decimal в hexadecimal. Ако преобразувате 2314885530818450000 в hex, то ще получите 2020202020201200. Доста повторения в началото, нали? Нека сега този hex код да го преобразуваме в текст:
Тук нещата се изясняват - HEX код 20 всъщност се преобразува в празен интервал. Очевидно тези 6 интервала се използват за подравняване на сумата в дясно. Значи става дума за проста програмна грешка.
Сега е ред на въпрос към вас. Колко американски долара реално струват закупените цигари?
Шестнайсетично 12 дава десетично 18, но дали долара или цента кой знае.
Това че има нули отзад предполага че формАта е double word, демек числото е 4 байта, и бих предположил, че банката иска да смята и центовете, така че вероятно числото е floating point.
Тоест 1,8 * 10^0, или 1 долар и 80 цента...
Това е да си американец... плащаш с кредитна карта нещо, което струва долар и осемдесе... и после се чудиш що си затънал в дългове до ушите :)
Поправка:
числото всъщност е 8 байта, или 64 бита.
Според IEEE стандартите: http://en.wikipedia.org/wiki/IEEE_754-2008
Предполагам, че използват този:
http://en.wikipedia.org/wiki/Double_precision,
което си е double в C/C++
Тоест имаме
1 знаков бит, 11 бита експонента, 52 бита мантиса
шестнайсетично число 0012, като младшите 4 байта се записват първи в паметта, и става 12 00.
Иначе резултата си е същия - долар и осемдесет.
Да, виждам че се оплетох в собствената си логика.
Явно това число не отговаря на тези стандарти, но не виждам как иначе може да са го направили, освен 1,8 * 10^0.
Отговора се крие в условието - по начина по който е преобразувано до 23 квадрилиона се вижда че числото не е с плаваща запетая. Затова направо го пействам в калкулатора и го преобразувам м/у другото се получава 2020202020201250, махам 20-ците и преобразувам 1250 в десетична и се получава 46.88 - може да си е купил цял стек или кодирането да не е толкова просто.