На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS

Дорогие друзья! Поздравляем вас с Новым 2018 годом!

Всем удачи, успеха и благополучия!
В новом году ожидаем новых рекордов при подсчёте количества ёлочек на экране ;)


msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Не поленитесь, загляните в эти разделы перед созданием темы. Возможно, так уже имеется решение вашего вопроса.

3. Настоятельно рекомендую обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).

Не забывайте также про главные ПРАВИЛА ФОРУМА!
Участники форума, нарушающие правила, будут наказываться, а вносящие вклад в развитие форума – приветствовать и, по возможности, награждаться :)

Приятного вам общения! ;)
Модераторы: Jin X, Qraizer
Страницы: (3) 1 2 [3]  все  ( Перейти к последнему сообщению )  
> floating-point invalid в dll
    Цитата leo @
    Учти, что вычисляется степень двойки, а двоичная мантисса любого числа 2N строго равна 1 и представляется абсолютно точно в любом вещественном формате.
    Это понятно, только ты из 2N не сможешь вычесть единицу, если N > 63 (для 80-битных чисел) или > 52 (для double), или > 23 (для single/float). А поскольку точность была настроена на double, то вычесть из 263 единицу не получалось, и в unsigned __int64 преобразовывалось не _I64_MAX, а _I64_MAX+1, и возникало исключение.

    Добавлено
    Цитата leo @
    в дельфях math.Power(..) для целых степеней считается через IntPower методом умножения
    И надо сказать, что это значительно быстрее, чем через fyl2x/f2xm1/fscale. Иногда в 2 раза, а иногда раз в 5-6 (при малых степенях). Специально мерил... :)
    Но там есть косяк (в Delphi): он не может вычислять степень > MaxInt (по модулю) из отрицательных чисел. Возникает исключение. Что в Delphi 7, что в Berlin. Т.е. если число > MaxInt или нецелое, он выполняет вычисление через fyl2x/f2xm1/fscale (и вылетает на fyl2x, соответственно).

    Добавлено
    Если кому надо – вот рабочая функция вычисления степени любого числа из любого. Вариант без IntPower (есть ещё и с IntPower).
    ExpandedWrap disabled
      ;##############################################
      ;##                                          ##
      ;##         -= FPU POWER FUNCTION =-         ##
      ;##       ФУНКЦИЯ ВОЗВЕДЕНИЯ В СТЕПЕНЬ       ##
      ;##                [ v1.00 ]                 ##
      ;##            MASM/TASM (16/32)             ##
      ;##                                          ##
      ;##   (c) 2017 by Jin X (jin.x@sources.ru)   ##
      ;##            http://xk7.ru/p/a/i           ##
      ;##                                          ##
      ;##############################################
       
      ;-- FPPower: функция возведения X в степень Y --------------------------------------------------------------------------
      ; Входные данные: st(0) = основание X, st(1) = показатель степени Y
      ; Результат: st(0) = st(0)^st(1) = X^Y (или 0 при ошибке), st(1) пуст; CF=NC=0 - успешный результат, CF=CY=1 - ошибка (при X<0 и нецелом Y)
      ; Функция изменяет AX, DX и флаги
       
      FPPower     proc
              ; Сравнение X с нулём
              ftst                ; st(0)=X=0 ?
              fstsw   ax
              mov dl,ah           ; dl and 1=1, если X<0 (используется в чистом FPU-расчёте и при проверке ошибки), иначе dl and 1=0
              sahf
              jz  short @@Zero        ; если X=0, результат=st(0)=0 (записываем чистый ноль - если допустим ноль со знаком, можно сделать прыжок на @@Free1AndExit); st(1)=Y; CF=NC=0
       
              ; Проверка Y на целое
              fld st(1)           ; st(0)=Y, st(1)=X, st(2)=Y
              frndint             ; st(0)=Round(st(0))=Round(Y), st(1)=X, st(2)=Y
              fcomp   st(2)           ; сравнение st(0) и st(2): Round(Y) и Y; st(0)=X, st(1)=Y, st(2) пуст
              fstsw   ax
              sahf
              jne short @@ErrChk      ; прыгаем, если Y нецелое
       
              ; Степень Y - целое число, проверяем знак X
              shr dl,1            ; проверяем знак X (dl and 1)
              jnc short @@PosX        ; прыгаем, если X>0 (dl=0)
       
              ; Проверка чётности целого Y (при X<0)
              fld1                ; st(0)=1, st(1)=X, st(2)=Y
              fld1                ; st(0)=st(1)=1, st(2)=X, st(3)=Y
              faddp               ; st(0)=2.0, st(1)=X, st(2)=Y
              fld st(2)           ; st(0)=Y, st(1)=2.0, st(2)=X, st(3)=Y
              fabs                ; st(0)=|Y|, st(1)=2.0, st(2)=X, st(3)=Y
              fprem               ; st(0)=|Y| mod 2.0 (если Y не чересчур большой, иначе st(0) будет содержать неверное значение, и тогда мы будем считать, что число чётное), st(1)=2.0, st(2)=X, st(3)=Y
              fld1                ; st(0)=1, st(1)=Y mod 2.0, st(2)=2.0, st(3)=X, st(4)=Y
              fcompp              ; сравнение st(0) и st(1): 1 и (Y mod 2.0) с удалением этих чисел; st(0)=2.0, st(1)=X, st(2)=Y, st(3) и st(4) пусты
              fstsw   ax
              shr ah,6            ; CF=ZF (т.к. нам надо получить CF=нечётный Y)
              sahf                ; CF=NC=0, если Y чётное; CF=CY=1, если Y нечётное
              fstp    st          ; удаляем 2.0; st(0)=X, st(1)=Y, st(2) пуст
              fabs                ; st(0)=|X|, st(1)=Y
          @@PosX: ; CF=NC=0, если dl and 1=0 (т.е. X>0, сюда был прыжок) или Y чётное
              fyl2x               ; st(0)=Y*log2(|X|)=Z,          st(1) пуст[st(0)=st(1)*log2(st(0))]
              fld st          ; st(0)=Z,              st(1)=Z
              frndint             ; st(0)=Round(Z),           st(1)=Z
              fxch                ; st(0)=Z,              st(1)=Round(Z)
              fsub    st,st(1)        ; st(0)=Z-Round(Z),         st(1)=Round(Z)
              f2xm1               ; st(0)=2^(E-Round(Z))-1,       st(1)=Round(Z)
              fld1                ; st(0)=1,              st(1)=2^(E-Round(Z))-1, st(2)=Round(Z)
              faddp   st(1),st        ; st(0)=st(0)+1 = 2^(E-Round(Z)),   st(1)=Round(Z),     st(2) пуст
              fscale              ; st(0)=2^(E-Round(Z))*2^Round(Z)=2^Z,  st(1)=Round(Z)  [st(0)=st(0)*2^RoundTowardZero(st(1))]
              ; st(0)=результат=X^Y
              jnc short @@Free1AndExit    ; прыгаем, если X>0, либо Y чётное
              fchs                ; иначе меняем знак результата
              clc             ; ошибок нет, CF=NC=0
          @@Free1AndExit:
              ffree   st(1)           ; удаляем лишнее значение st(1)=Round(Z) или st(1)=X; st(0)=результат
              ret
              ; Проверка ошибки (Y нецелое!)
          @@ErrChk:
              shr dl,1            ; проверяем знак X (dl and 1)
              jnc short @@PosX        ; прыгаем, если X>0 (dl=0; CF=NC=0)
              ; иначе ошибка (dl=1: X<0 и Y нецелое); CF=CY=1
          @@Zero:
              fldz                ; st(0)=0, st(1)=X, st(2)=Y
              ffree   st(2)           ; удаляем лишнее значение st(2)=Y
              jmp short @@Free1AndExit
      FPPower     endp
    user posted image Чат форума в Telegramuser posted image Чат форума в Discord (жми и подключайся!) ;)
    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
    0 пользователей:
    Страницы: (3) 1 2 [3]  все


    Рейтинг@Mail.ru
    [ Script Execution time: 0,0890 ]   [ 17 queries used ]   [ Generated: 24.01.18, 11:30 GMT ]