Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

UoKit.com Форумы _ Плагины и доп. ПО _ Математические операции с плавающей точкой.

Автор: DarkMaster 26.10.2015, 18:57

Данный плагин позволяет производит математические операции с числами с плавающей точкой.
Плагин необходимо поместить в папку Plugins рядом с uopilot.exe. Для работы требуются установленные библиотеки c++:
http://www.microsoft.com/ru-ru/download/details.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 может быть не корректным.



Прикрепленные файлы
Прикрепленный файл  math.zip ( 3,85 килобайт ) Кол-во скачиваний: 1608

Автор: cirus 27.10.2015, 2:33

Цитата
Пример:
set %a (12.1 / 3)

Код
set %a math.dbl (12.1 / 3)

Автор: DarkMaster 27.10.2015, 6:08

Спасибо.

Автор: cirus 13.11.2015, 2:26

Скрипт 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 13.11.2015, 11:14

Надо тыкать кнайта. Что-то не так с областями видимости походу.

Автор: DarkMaster 2.4.2016, 10:21

Проблема оказалась в изменении локали плагином для поиска окон. Локаль сохраняется и приводит к тому, что стандартная функция c++ перестает воспринимать точку, как десятичный разделитель, и требует запятую. Запятую можешь не ставить - они заменяются на точки при парсинге строки. В описании функции с++, которая начинает сыпаться явно указано "десятичная точка", т.е. по сути получается нарушение стандарта.

Автор: cirus 2.4.2016, 10:41

Так с точкой также результат 0.

Автор: DarkMaster 2.4.2016, 10:49

Дык в том то и фишка, что он запятую требует после плагина с поиском окон. А запятая не пройдет, т.к. все запятые автоматически заменяются на точки для соответствия заявленным стандартам.

Автор: cirus 2.4.2016, 11:01

Так плагин с точкой тоже должен работать.

Код
set %b WindowStatus.find (1111 *UoPilot  v2.35   WK* TfmMain)
set %a math.dbl (1234.567 / 37)     //тут нет запятых
log %a [1]

Автор: DarkMaster 2.4.2016, 11:22

Цитата
Так плагин с точкой тоже должен работать.

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

Может так будет понятнее. Самое начало функции, собственно парсинг:
Код
    // Заменяем все запятые на точки.
    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 2.4.2016, 12:07

Т.е. только перезагружать плагины?

Код
set %b WindowStatus.find (1111 *UoPilot  v2.36.1   WK* TfmMain)
pluginreload
set %a math.dbl (1234,567 / 37)
log %a [1]

Автор: DarkMaster 2.4.2016, 12:18

Ну пока - да. Вообще могу под запятую быро скомпилить. Кнайт не вовремя свалил из аськи. Надо обсудить и понять, что с этим делать. Со своей стороны я могу и локаль принудительно менять под нужную и попробовать изменить плагин поиска окна. Т.е. решить проблему можно и на моей стороне без особых трудозатрат. Просто надо понять, как это сделать наиболее корректно.

Автор: FREEON 15.6.2019, 1:19

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

Автор: cirus 15.6.2019, 2:26

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

Плагин использовать или писать скрипт на луа.

Автор: FREEON 15.6.2019, 15:04

а чо когда выполняю такой код

Код
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 15.6.2019, 19:08

В первом посте пример есть:

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

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

Зачем?

Автор: FREEON 15.6.2019, 19:40

Цитата(cirus @ 15.6.2019, 19:08) *

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


Зачем?

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

Автор: cirus 15.6.2019, 20:44

Цитата
Да как бы нужно значения до тысячных этот скрипт заточен под генерацию кода 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 27.6.2019, 19:35

Цитата(FREEON @ 15.6.2019, 1:19) *

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

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

Автор: FREEON 27.6.2019, 20:53

Цитата(Fors1k @ 27.6.2019, 19:35) *

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

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

Автор: Fors1k 27.6.2019, 22:36

Цитата(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 27.6.2019, 22:59

Оставит после зяпятой нужное количество знаков, или вернёт целое число.

Код
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 28.6.2019, 0:58

Пример
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 7.7.2019, 4:02

Цитата(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 24.7.2019, 3:20

Ну наконец-то я придумал как это провернуть) Изображение
Итак, для всех, кто мечтал об операциях с дробными числами в одну строку кода, как например:

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




Совет:
Для использования нужно скачать файл.
Прикрепленный файл  math.txt ( 467 байт ) Кол-во скачиваний: 914
В пилоте кликнуть Скрипт->Открыть файл процедур..

Автор: Cockney 24.7.2019, 12:56

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

Автор: Fors1k 24.7.2019, 14:40

Цитата(Cockney @ 24.7.2019, 12:56) *

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

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

Автор: DarkMaster 27.7.2019, 19:13

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

Lua

Автор: Fors1k 27.7.2019, 19:33

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

Lua

Данный топик иммет какое-либо отношение к луа? Или нужно у Cockney спрашивать разрешение в каких топиках и о каких языках программирования мне общаться?
Я еще хочу дописать возможность делать сравнения a > b ; a < b ; a = b. Надеюсь он не будет против...Изображение

Автор: DarkMaster 27.7.2019, 23:58

Fors1k, не нужно воспринимать это так в штыки. Вы можете использовать любые языки, вам никто не запрещает и имелось ввиду совсем иное. Lua был встроен чтобы решить очень многие проблемы пилота в части скриптового движка - они были при этом решены. Вы по своим соображениям выбираете старый синтаксис, который не содержит этих решений. Это ваше право и никто его не отбирает, но со стороны возникают логичные вопросы о целесообразности данных действий и вам намекают, что возможно стоит перестать хвататься за старое, но столь привычное. Есть некоторые старые очень объемные вещи и у меня, которые я не готов переводить на луа, но каждый раз, когда нужно что-то там править для меня это целая беда . Присмотритесь, возможно пришло время и не более того.

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

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

Автор: Fors1k 28.7.2019, 1:54

Цитата(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



Совет:
Для использования нужно скачать файл.
Прикрепленный файл  math.txt ( 1004 байт ) Кол-во скачиваний: 2887
В пилоте кликнуть Скрипт->Открыть файл процедур..

Автор: Fors1k 2.8.2019, 0:23

Добавил возможность через 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


Совет:
Для использования нужно скачать файл.
Прикрепленный файл  math.txt ( 1,21 килобайт ) Кол-во скачиваний: 2780
В пилоте кликнуть Скрипт->Открыть файл процедур..

Автор: Fors1k 15.8.2019, 18:44

Добавил условие неравенства.

При повторном/многократном сравнении через одну и ту же переменную($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


Совет:
Для использования нужно скачать файл.
Прикрепленный файл  math.txt ( 1,34 килобайт ) Кол-во скачиваний: 3516
В пилоте кликнуть Скрипт->Открыть файл процедур..

Автор: minfin 27.11.2019, 8:00

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

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

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

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

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

U MAKE MY DAY.

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

<3

Автор: Fors1k 28.11.2019, 20:00

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

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

U MAKE MY DAY.

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


Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)