Строка в число - можно ли без перемножений?

Тема в разделе "WASM.ASSEMBLER", создана пользователем Antolflash, 4 апр 2009.

  1. Antolflash

    Antolflash New Member

    Публикаций:
    0
    Регистрация:
    14 дек 2008
    Сообщения:
    167
    Всем известен метод перевода строки в число, если на входе , предположим, десятичное "273", то это 3*(10^0) + 7*(10^1) + 2*(10^2). Т.к. в таблице ASCII числа идут по возрастанию от нуля, то достаточно вычесть 0x30 из каждого числа, чтобы получить его не в виде кода, а в виде реальной цифры. Только вот возник вопрос. Если на входе десятичное число, то можно ли, обойтись без "долгой" операции умножения. В случаи маленьких чисел - нам всё равно. В случаи целых чисел с длинной до 80бит можно подключить спороцессор. Он будет работать быстрее, чем если я сам напишу функции сложения, вычитания, умножения, деления столбиком (так ли это?) (а вот если числа будут больше 80бит, то тогда только столбиком можно). Если рассматривать случай ооочень длинных чисел, то тут всё безхитростно, я не слышал, чтобы были какие-то разные алгоритмы операций столбиком. Но рассмотрим случай с числом меньше 80бит. Это шестнадцатеричные числа с 20ю разрядами. Это же предётся умножать на 16^20, 16^19 и т.д. Как я понимаю побитовым сдвигом влево, т.е. SHL. мы получим степени 16и. А вот дальше придётся умножать разряды на эти полученные числа-степени16и.. Как это обойти?
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Во-первых, в 80-битном вещественном формате (extended) мантисса составляет только 64 бита, а старшие 16 бит занимают двоичный порядок + бит знака. Поэтому точно в этом формате можно представить только 64-битные целые.
    Во-вторых, для умножения целых чисел на 10 используется "быстрая" комбинация lea eax,[eax+eax*4] + add eax,eax
    В-третьих, преобразование строки в число до 64 бит можно делать по частям: формируем первое число A до 9 десятичных знаков - запоминаем, затем формируем второе число B с подсчетом числа знаков N, затем вычисляем итог как A*10^N+B. Степень 10-ки можно взять из таблицы
     
  3. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    интересный вариант, спасибо :)
     
  4. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    MSoft
    А ты не знал ?! Во-всех вариациях atoi, StrToInt и т.п. юзается ;)

    PS: вместо add eax,eax можно сразу и очередную цифру из edx прибавлять lea eax,[edx+eax*2]
     
  5. ava

    ava New Member

    Публикаций:
    0
    Регистрация:
    11 окт 2003
    Сообщения:
    169
    Ничего не понял.

    Специально для таких случаев придуманы упакованые десятчные числа (packed decimal). Размер - 80 бит, старший бит - знаковый, младшие 72 бита - 18 десятичных цифр, по 4 бита на цифру, биты 72 - 78 не используются. Преобразуешь строку в упакованное десятичное, затем выполняешь:

    Код (Text):
    1. fbld    tbyte ptr Packed80
    2. fistp   qword ptr Int64
    и теперь в Int64 лежит готовое число.
     
  6. Gray

    Gray New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2004
    Сообщения:
    75
    Адрес:
    Russia
    Вообще-то достаточно уметь умножать на 10, просто переписав выражение a*(10^0) + b*(10^1) + c*(10^2) + d*(10^3)... в виде a+10*(b+10*(c+10*d)). Но и умножать не надо, как уже было отмечено коллегами. А если интересуют операции с о-о-о-очень длинными цифрами, советую глянуть http://pari.math.u-bordeaux.fr/ Там и исходники есть.
     
  7. deLight

    deLight New Member

    Публикаций:
    0
    Регистрация:
    26 май 2008
    Сообщения:
    879
    а если динамика?
    для каждого разряда составить таблицу со значениями, вычисление индекса сдвигом - а дальше только сложение. возможно конечно от такой идеи толку ноль, надо прикидывать что получится...
     
  8. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    и как ты себе это представляешь.
    первый разряд 00001111b = 1|2|3|4|5|6|7|8|9
    второй разряд 01111110b = 10|20|30|40|50|60|70|80|90
    третий разряд ...
    ну из-за того что 10=2*2*2+2 ничего не получится (вот убери лишнюю 2 и все прекрасно)
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    ava
    Не думаю, что они были придуманы "специально для этого" ;)
    Одно только преобразование строки к формату BCD, займет не меньше времени, чем непосредственной формирование пары чисел с использованием быстрого умножения на lea. Плюс команда fbld на современных компах отнюдь не быстрая - от 40-45 тактов на P6 и атлонах до 80-90 тактов на P4. Плюс возможный штраф, сравнимый с длиной конвеера, на чтение целого после частичной записи (STLF restriction), плюс опасность реплэя на первых моделях P4
     
  10. murder

    murder Member

    Публикаций:
    0
    Регистрация:
    3 июн 2007
    Сообщения:
    628
    Может как-нибудь так
    Код (Text):
    1. org 100h
    2.  
    3. movaps    xmm0,dqword[s]
    4. psubusb   xmm0,dqword[a]
    5. pmaddubsw xmm0,dqword[b]
    6. pmaddwd   xmm0,dqword[c]
    7. pmullw    xmm0,dqword[d]
    8. phaddd    xmm0,xmm0
    9. phaddd    xmm0,xmm0
    10. movd      eax,xmm0
    11.  
    12. cmp eax,123
    13. @@:je @b
    14. ret
    15.  
    16. align 16
    17. s db '123',0
    18.   rb 16
    19. a db 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48
    20. b db 1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10
    21. c dw 1,100,1,100,1,100,1,100
    22. d dd 1,10000,100000000,0
    P.S. код не проверял т.к. нету SSE3