Помощь - Поиск - Пользователи - Календарь
Полная версия: Математические операции с плавающей точкой.
UoKit.com Форумы > Кликер > UO Pilot > Плагины и доп. ПО
DarkMaster
Данный плагин позволяет производит математические операции с числами с плавающей точкой.
Плагин необходимо поместить в папку Plugins рядом с uopilot.exe. Для работы требуются установленные библиотеки c++:
http://www.microsoft.com/ru-ru/download/de...s.aspx?id=40784

Код
math.dbl (<var1> <sign> <var2>)
<var1> - первое число (может быть не целым).
<sign> - знак математической операции (+-/*).
<var2> - второе число (может быть не целым).
Корректной последовательностью чисел с плавающей точкой для считается последовательность, удовлетворяющая следующим условиям:
    Знак положительного или отрицательного числа (необязательно).
    Последовательность цифр, как вариант, может содержать десятичную точку или запятую.
    Дополнительная экспонентная часть, которая сама по себе состоит из символа 'e' или 'E',
        после которого следует дополнительный знак и последовательность цифр.
Диапазон значений:
    min:  2,2250738585072014 E – 308
    max: 1,7976931348623158 E + 308

Результат работы функции должен быть присвоен массиву. Возвращаемые значения:
%a [1] - результат математической операции. Если функция завершилась с ошибкой, вернет "0".
%a [2] - возвращает OK, если функция успешно выполнена, Error, если произошла ошибка.
%a [3] - расшифровка ошибки:
Succes - функция завершилась успешно. (%a [2]="OK")
First value: ERANGE - первый параметр за пределами допустимого значения.
Second value: ERANGE - второй параметр за пределами допустимого значения.
No sign: [символ] - знак математической операции не найден.

Пример:
set %a math.dbl (12.1 / 3)
log Результат вычислений: %a [1]
log Ошибка: %a [2]
log Текст ошибки: %a [3]

В плагин не следует передавать несколько математический операций, использовать скобки и т.д.
Функция должна принять только перечисленные выше параметры.
Если необходимо произвести какие-либо длинные математические вычисления,
то производите их до передачи параметров или используйте eval().
При работе с числами с плавающей точкой нужно понимать:
Расчет формулы «x2-y2» лучше вычислять используя формулу «(x-y)(x+y)».
В арифметике с плавающей запятой правило (a*b)*c = a*(b*c) не выполняется для любых арифметических операций.
Не все десятичные числа имеют двоичное представление с плавающей запятой. Например, число «9999999999.2» будет представлено как «9999999999.200001».
При сравнении чисел с плавающей точкой не корректно выражение:
a < b
Для подобного сравнения правильным будет сравнение разницы чисел с некоторой константой:
c = a - b
abs(c) < 0.1
0.1 взято для примера, точность вы можете задать самостоятельно.

Так же необходимо понимать, что использование чисел с плавающей точкой(в т.ч. их разницы) в пилоте
по средствам оператора if может быть не корректным.
cirus
Цитата
Пример:
set %a (12.1 / 3)

Код
set %a math.dbl (12.1 / 3)
DarkMaster
Спасибо.
cirus
Скрипт 1, работает, проблем нет
Код
set %a math.dbl (1234,567 / 37)
log %a [1]
stop_script

Скрипт 2, не работает
Код

set %b WindowStatus.find (1111 *UoPilot  v2.35   WK* TfmMain)       //поиск пилота (работает, тут нет проблем)
set %a math.dbl (1234,567 / 37)
log %a [1]    //результат 0
stop_script

Лог второго скрипта
Код
set %b WindowStatus.find (1111 *UoPilot  v2.35   WK* TfmMain)
%TfmMain) [ 2 1 ] = 525014
set %a math.dbl (1234,567 / 37)
%37) [ 4 1 ] = No sign: .
log %a(0) [1]
0
stop_script

Если использовать плагин для поиска окна, причём в любой вкладке, то математические операции после этого не работают. Начнут работать только после перезапуска пилота.
No sign:, почему-то не видит знак операции.
DarkMaster
Надо тыкать кнайта. Что-то не так с областями видимости походу.
DarkMaster
Проблема оказалась в изменении локали плагином для поиска окон. Локаль сохраняется и приводит к тому, что стандартная функция c++ перестает воспринимать точку, как десятичный разделитель, и требует запятую. Запятую можешь не ставить - они заменяются на точки при парсинге строки. В описании функции с++, которая начинает сыпаться явно указано "десятичная точка", т.е. по сути получается нарушение стандарта.
cirus
Так с точкой также результат 0.
DarkMaster
Дык в том то и фишка, что он запятую требует после плагина с поиском окон. А запятая не пройдет, т.к. все запятые автоматически заменяются на точки для соответствия заявленным стандартам.
cirus
Так плагин с точкой тоже должен работать.
Код
set %b WindowStatus.find (1111 *UoPilot  v2.35   WK* TfmMain)
set %a math.dbl (1234.567 / 37)     //тут нет запятых
log %a [1]
DarkMaster
Цитата
Так плагин с точкой тоже должен работать.

Должен, пока другой плагин не подменил локаль.
Считай делиметр он изменяет.

Может так будет понятнее. Самое начало функции, собственно парсинг:
Код
    // Заменяем все запятые на точки.
    for (unsigned char i = 0; ParamStruct->ParamString[i] != '\0'; i++){
        if (ParamStruct->ParamString[i] == ','){
            ParamStruct->ParamString[i] = '.';
        }
    }


    char * pPos; // Указатель на последний символ разобранной строки +1 (вернет значение).
    double firstVal = strtod(ParamStruct->ParamString, &pPos) // А вот тут будет ошибка;

Если запятые на точки не менять - работать не будет со стандартной локалью. Если локаль русская, то замена точек на запятые не нужна и приводит к ошибке.
cirus
Т.е. только перезагружать плагины?
Код
set %b WindowStatus.find (1111 *UoPilot  v2.36.1   WK* TfmMain)
pluginreload
set %a math.dbl (1234,567 / 37)
log %a [1]
DarkMaster
Ну пока - да. Вообще могу под запятую быро скомпилить. Кнайт не вовремя свалил из аськи. Надо обсудить и понять, что с этим делать. Со своей стороны я могу и локаль принудительно менять под нужную и попробовать изменить плагин поиска окна. Т.е. решить проблему можно и на моей стороне без особых трудозатрат. Просто надо понять, как это сделать наиболее корректно.
FREEON
Есть в 2019 году способ умножения десятичных чисел?
cirus
Цитата
Есть в 2019 году способ умножения десятичных чисел?

Плагин использовать или писать скрипт на луа.
FREEON
а чо когда выполняю такой код
Код
set %arr [1 13] 8
set %op [1 2] math.dbl (%arr [1 13] * 2.25)
log %op [1 2]
end_script

в лог выдает:
Цитата
18,000000
OK
Succes

нельзя ли в таком виде отбросить лишнее отображение ок и третей строки? а также чо он не округляет цифры? Как округлить до тысячных или до сотых или десятых если на конце 0. К целым то понятно есть round или trunc а вот до тысячных не знаю. Задать бы как что бы после запятой или точки копировало 3 цифры то можно было бы использовать функцию Delete, но не известно из скольких символов будет состоять целая часть
cirus
В первом посте пример есть:
Код
set %a math.dbl (12.1 / 3)
log Результат вычислений: %a [1]
end_script

Цитата
Как округлить

Зачем?
FREEON
Цитата(cirus @ 15.6.2019, 19:08) *

В первом посте пример есть:
Код
set %a math.dbl (12.1 / 3)
log Результат вычислений: %a [1]
end_script


Зачем?

Да как бы нужно значения до тысячных этот скрипт заточен под генерацию кода wiki страничек. Конечно можно вручную править оно не сложно, но если есть возможность как то это избежать то сами понимаете лишний гемор не к чему
cirus
Цитата
Да как бы нужно значения до тысячных этот скрипт заточен под генерацию кода wiki страничек.

Лучше луа для этого. Синтаксис пилота не слишком удобен для работы со строками.
Код
set %a math.dbl (8 * 2.26)

log clear
log mode compact
log Результат вычислений: %a [1]

set $temp %a [1]
set $a trunc($temp)
set $b frac($temp)

while 1 = 1
    set $temp copy($b size($b) 1)
    if  $temp = 0
        set $b Delete($b size($b) 1)
    else
        break
    end_if
end_while

set %a[1] $a
if  $b != ""
    set %a [1 2] ","
    set %a [1 3] $b
end_if
log %a [1]
end_script
Fors1k
Цитата(FREEON @ 15.6.2019, 1:19) *

Есть в 2019 году способ умножения десятичных чисел?

Имеется в виду, что дробные числа будут только в аргументах? На выходе устроит целое число?
FREEON
Цитата(Fors1k @ 27.6.2019, 19:35) *

Имеется в виду, что дробные числа будут только в аргументах? На выходе устроит целое число?

Не, результат тоже нужен был нецелым(если таковым получается). Так как нецелое можно представить в виде:
2,5 = 25/10
1,66 = 166/100
и т.д.
Fors1k
Цитата(FREEON @ 15.6.2019, 15:04) *

Задать бы как что бы после запятой или точки копировало 3 цифры.

Оставит после зяпятой нужное количество знаков.
Код
set #f 3 // здесь задать кол-во знаков после запятой
set %a math.dbl (12.1 / 3)
set $a %a[1]
set $a copy($a 1 eval(posex("," $a)+#f))
log $a
end_script
Fors1k
Оставит после зяпятой нужное количество знаков, или вернёт целое число.
Код
set #f 3 // здесь задать кол-во знаков после запятой
set %a math.dbl (10 / 5)
set $a %a[1]
if frac($a) > 0
set $a copy($a 1 eval(posex("," $a)+#f))
else
set $a trunc($a)
end_if
log $a
end_script
Fors1k
Пример
59,4/11+2,3*2
Код
set %a math.dbl (59.4 / 11)
  call r %a[1]
  set $a $r
set %b math.dbl (2.3 * 2)
  call r %b[1]
  set $b $r
set %c math.dbl ($a + $b)
  call r %c[1]
  set $c $r
log $c
end_script
proc r $x
set linedelay 1
set #f 3
if frac($x) > 0
   set $result copy($x 1 eval(posex("," $x)+#f))
else
   set $result trunc($x)
end_if
end_proc
Fors1k
Цитата(FREEON @ 15.6.2019, 15:04) *

Нельзя ли отбросить лишнее отображение ок и третей строки?
Как округлить до тысячных или до сотых или десятых если на конце 0.

Код самого округления сокращен до 1 строки.
Отбрасываются все нули в конце.

Пример результата:
Код
3,000000 = 3
3,007000 = 3,007
3,373000 = 3,373
3,333333 = 3,333333

Пример кода:
Код
set $a math.dbl (59.4 / 11)
  call m $a
  set $a $m
set $b math.dbl (2.202 * 2)
  call m $b
  set $b $m
set $c math.dbl ($a + $b)
  call m $c
  set $c $m
log $c
end_script
proc m $x
  set #n regexp (#p $result $x (\d+?(?=,0+\b)|\d+[,.]\d+?(?=0+\b)|\d+[,.]\d+))
end_proc
Fors1k
Ну наконец-то я придумал как это провернуть) Изображение
Итак, для всех, кто мечтал об операциях с дробными числами в одну строку кода, как например:
set $a 59.4 / 11
и в переменной $a сразу был бы ответ 5,4 ( без массивов, выбора в нем первой строки, лишних нулей в конце и т.д. ).

......................................................
call m $var <arg1> <sign> <arg2>
......................................................

call m $a 59.4 / 11
В переменной $a сразу будет ответ 5,4 . Так же будет проверяться корректность операции.

В примере ниже три математические операции с плавающей точкой в трех строках.
Код
call m $a 59.4 / 11
call m $b 2.202 * 2
call m $c $a + $b
log Ответ: $c
end_script

При повторном/многократном использовании одной и той же переменной, которая получает результат, следует использовать запись: call m "$var" <arg1> <sign> <arg2> .
Код
call m  $a 59.4 / 11
call m "$a" 2.202 * 2
log Ответ: $a
end_script




Совет:
Для использования нужно скачать файл.
Нажмите для просмотра прикрепленного файлаВ пилоте кликнуть Скрипт->Открыть файл процедур..
Cockney
"...плакали, кололись, но продолжали грызть кактус."
Fors1k
Цитата(Cockney @ 24.7.2019, 12:56) *

"...плакали, кололись, но продолжали грызть кактус."

У тебя вопрос какой-то есть, или предложение по теме ?
DarkMaster
Цитата
У тебя вопрос какой-то есть, или предложение по теме ?

Lua
Fors1k
Цитата(DarkMaster @ 27.7.2019, 19:13) *

Lua

Данный топик иммет какое-либо отношение к луа? Или нужно у Cockney спрашивать разрешение в каких топиках и о каких языках программирования мне общаться?
Я еще хочу дописать возможность делать сравнения a > b ; a < b ; a = b. Надеюсь он не будет против...Изображение
DarkMaster
Fors1k, не нужно воспринимать это так в штыки. Вы можете использовать любые языки, вам никто не запрещает и имелось ввиду совсем иное. Lua был встроен чтобы решить очень многие проблемы пилота в части скриптового движка - они были при этом решены. Вы по своим соображениям выбираете старый синтаксис, который не содержит этих решений. Это ваше право и никто его не отбирает, но со стороны возникают логичные вопросы о целесообразности данных действий и вам намекают, что возможно стоит перестать хвататься за старое, но столь привычное. Есть некоторые старые очень объемные вещи и у меня, которые я не готов переводить на луа, но каждый раз, когда нужно что-то там править для меня это целая беда . Присмотритесь, возможно пришло время и не более того.

Цитата
Я еще хочу дописать возможность делать сравнения a > b ; a < b ; a = b.

И я буду вам благодарен
Fors1k
Цитата(DarkMaster @ 27.7.2019, 23:58) *
Цитата
Я еще хочу дописать возможность делать сравнения a > b ; a < b ; a = b.

И я буду вам благодарен

Вроде доделал.
......................................................
call m $var <arg1> <sign> <arg2>
if $var
...
end_if

......................................................
При повторном/многократном сравнении через одну и ту же переменную($if) следует использовать запись: call m "$var" <arg1> ? <arg2> .
Код
call m $a 5.409 * 2.7
log $a
call m $if $a > 10.25
if $if
    log Yes
else
    log No
end_if
end_script



Совет:
Для использования нужно скачать файл.
Нажмите для просмотра прикрепленного файлаВ пилоте кликнуть Скрипт->Открыть файл процедур..
Fors1k
Добавил возможность через switch сделать ветвление по условиям > ; < ; =.
......................................................
call m $var <arg1> ? <arg2>
......................................................
При повторном/многократном сравнении через одну и ту же переменную($sw) следует использовать запись: call m "$var" <arg1> ? <arg2> .

Пример.
Допустим, нам нужно скопирвать число, и сделать одно из трех действий, в зависимости от его отношения к другому числу.
Код
double_kleft x y
get clipboard $a

call m $sw $a ? 114.58
switch $sw
    case >
        log arg1 больше
        break
    case <
        log arg1 меньше
        break
    case =
        log arg1 и arg2 равны
        break
end_switch
End_script


Совет:
Для использования нужно скачать файл.
Нажмите для просмотра прикрепленного файлаВ пилоте кликнуть Скрипт->Открыть файл процедур..
Fors1k
Добавил условие неравенства.

При повторном/многократном сравнении через одну и ту же переменную($if) следует использовать запись: call m "$var" <arg1> <sign> <arg2> .
Код
call m $a 5.505 * 2
log $a
call m $if $a != 11.01
if $if
    log Yes
else
    log No
end_if
end_script


Совет:
Для использования нужно скачать файл.
Нажмите для просмотра прикрепленного файлаВ пилоте кликнуть Скрипт->Открыть файл процедур..
minfin
ВАХ, спасибо БОЛЬШОЕ, Форсик.

трое суток учил Lua. = ото уж точно "продолжали грызть кактус"

список функций не полный. всё-равно костыль на костыле. не понятный скрипт в непонятном скрипте.

уже даже задумывался передавать через пилот в SQL, от туда считать через php.

и даже не думал что решится так просто.

U MAKE MY DAY.

позволь угостить тебя хорошим чаем. скинь реквы в личку.

<3
Fors1k
Цитата(minfin @ 27.11.2019, 8:00) *

ВАХ, спасибо БОЛЬШОЕ, Форсик.

U MAKE MY DAY.

minfin, рад, что тебе это облегчило жизнь, и благодарю за столь лестные слова в адрес моих трудов;))

Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.
Русская версия Invision Power Board © 2001-2024 Invision Power Services, Inc.