C, PHP, VB, .NET

Дневникът на Филип Петров


* Кутия цигари

Публикувано на 17 юли 2009 в раздел Математика.

Попаднах на интересна статия от сайта Consumerist. Преди два-три дни в американската преса гръмна забавна новина. Американецът Джон Мужински отишъл да си купи цигари. Платил с кредитната си карта VISA, взел касовата си бележка и тръгнал по работа.

След малко обаче погледнал бележката и останал като гръмнат – оказало се, че са му взели 23 квадрилиона долара. Точната сума всъщност била $23 148 855 308 184 500.00. Естествено ставало дума за програмна грешка – системата на VISA се била „бъгнала“.

Сметка

Няколко часа отнели на Джон докато оправи бъкиите си с банката. В крайна сметка всичко завършило благополучно и дори таксата от 20 долара за прехвърляне на лимита му била опростена.

Интересно е да се разровим по-дълбоко в случая. Защо се е получила точно тази сума? Изглежда достатъчно произволна, нали?

Първото предположение, че става дума за зимбабвийски долари, естествено се оказало грешно:

Зимбабвийски Долари

Отговорът на загадката се крие в преобразуване на числото от decimal в hexadecimal. Ако преобразувате 2314885530818450000 в hex, то ще получите 2020202020201200. Доста повторения в началото, нали? Нека сега този hex код да го преобразуваме в текст:

HEX code

Тук нещата се изясняват – HEX код 20 всъщност се преобразува в празен интервал. Очевидно тези 6 интервала се използват за подравняване на сумата в дясно. Значи става дума за проста програмна грешка.

Сега е ред на въпрос към вас. Колко американски долара реално струват закупените цигари?

 



4 коментара


  1. Светльо Антонов каза:

    Шестнайсетично 12 дава десетично 18, но дали долара или цента кой знае.
    Това че има нули отзад предполага че формАта е double word, демек числото е 4 байта, и бих предположил, че банката иска да смята и центовете, така че вероятно числото е floating point.
    Тоест 1,8 * 10^0, или 1 долар и 80 цента…
    Това е да си американец… плащаш с кредитна карта нещо, което струва долар и осемдесе… и после се чудиш що си затънал в дългове до ушите :)

  2. Светльо Антонов каза:

    Поправка:
    числото всъщност е 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.
    Иначе резултата си е същия – долар и осемдесет.

  3. Светльо Антонов каза:

    Да, виждам че се оплетох в собствената си логика.
    Явно това число не отговаря на тези стандарти, но не виждам как иначе може да са го направили, освен 1,8 * 10^0.

  4. Mertol каза:

    Отговора се крие в условието – по начина по който е преобразувано до 23 квадрилиона се вижда че числото не е с плаваща запетая. Затова направо го пействам в калкулатора и го преобразувам м/у другото се получава 2020202020201250, махам 20-ците и преобразувам 1250 в десетична и се получава 46.88 – може да си е купил цял стек или кодирането да не е толкова просто.

Добави коментар

Адресът на електронната поща няма да се публикува


*