Заметил, что данные функции дают разные ответы при r = 9.9999, например.
function R2IX takes real r returns integer
    local integer i = R2I(r)
    if r - I2R(i) >= 1. then
        return i + 1
    endif
    return i
endfunction
// Ответ: 9.

function R2IY takes real r returns integer
    local integer i = R2I(r)
    if r - I2R(i) == 1. then
        return i + 1
    endif
    return i
endfunction
// Ответ: 10.
Почему так происходит? Какие операции сравнения (==, !=, >, <, >=, <=) лучше использовать для типа real?

Принятый ответ

Clamp:
Статью уже кидали, ответа на вопрос там нет.
Давно видел эту статейку на HIVE, думал, что её уже давно кинут сюда)
Там и есть ответы на интересующие меня вопросы.
Вот тут ещё об этом.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
19
6 лет назад
0
Похожие вопросы:

ответ
спасибо всем, подали пару идей. буду работать
ответ
Примерно так, только вместо класса - тип предмета.
Событие - Юнит получает предмет.
Ну и можно кинуть предмет не из слота, а подобранный.
ответ
еще можно дать нужным юнитам абилку без иконки (например предметную +0 атаки) и проверять что она у них есть
ответ
Roy Mustang:
ответ
любой штатный способ быстрее любого велосипеда. группа будет быстрее перебора массива юнитов. переменная лучше, чем постоянные GetFilterUnit()
если дашь мне код в чистом жассе, я могу прямо в лайве замеры сделать

2
20
6 лет назад
2
Коротко: математические операции с числами с плавающей запятой с разным числом знаков (после запятой - точно, по идее и до должно учитываться, но тут не уверен... 1.+99.=100.?) порождают погрешность. Так, 0,02+0,1 != 0,12.
В вц3 следует сравнивать с диапазоном. x <= z and x >= y. Либо с R2I(x * 10^y)
Подробнее можно прочитать, например, на хабре
2
18
6 лет назад
Отредактирован Hodor
2
Внутри функции R2I все числа округляются, так к примеру (9.9999/2) для игры станет (9/2), а т.к. 4.5 != челое число, значит в ответе будет 4
Вне функции R2I, реальное число автоматически округляется до целого, если до целого числа ему остается 0.0001 или меньше
К примеру: 9.9999 станет 10.000, или 1.0001 станет 1.000
Теперь сам вопрос - баг решается примерно так
function R2IX takes real r returns integer

    local integer i = R2I(r)
    local real    x = r - I2R(i)

    if x > 1. or x == 1. then
        return i + 1
    endif

    return i

endfunction
0
28
6 лет назад
Отредактирован PT153
0
Ребята, а вы читали вопрос, смотрели функции? Потому что ваши ответы никак не отвечают на вопросы.
UrsaBoss, ты написал такую же функцию, что и у меня в вопросе (только разделил => на > и ==). Причём тут 9.9999/2?
К примеру: 9.9999 станет 10.000, или 1.0001 станет 1.000
Это не так, я только что тестировал, в JASS действительные числа часто точны до 6-го знака после запятой, точно до 4-го. R2SW адекватно работает при precision < 7, при бОльших значениях часто выдаёт бред.
Я повторю вопросы ещё раз:
  1. Почему когда я использую >= получаю верный ответ, а когда ==, то неверный, хотя => сильнее ==? R2I(9.9999) = 9, это я проверял, тогда 9.9999 - 9.0 == 1 выдаёт правду, но 9.9999 - 9.0 >= 1 выдаёт ложь. Как так?
  2. Какие операции сравнения (==, !=, >, <, >=, <=) лучше для действительных чисел в JASS (слышал и убедился сам, что сравнение через == плохо)?
Я знаю про стандарт IEEE754 и про неточность арифметических действий с float, меня интересует лишь сравнение этих чисел конкретно в JASS.
Тесты, что я проводил:
Test 1
function R2Idown takes real r returns integer
    local integer i = R2I(r)
    if r - I2R(i) >= 1. then
        return i + 1
    endif
    return i
endfunction

function R2Iup takes real r returns integer
    local integer i = R2I(r)
    if r > I2R(i) then
        return i + 1
    endif
    return i
endfunction

...
    set r = 9. // от 9. до 9.9999999999
    set r2i = R2I(r)
    set r2idown = R2Idown(r) // "исправленная" R2I()
    set r2iup = R2Iup(r)
    call DebugMsg("Real: x") // вместо x значение r, записанное вручную.
    call DebugMsg("R2S: " + R2S(r))
    call DebugMsg("R2SW-1: " + R2SW(r, 0, -1))
    call DebugMsg("R2SW0: " + R2SW(r, 0, 0))
    call DebugMsg("R2SW6: " + R2SW(r, 0, 6))
    call DebugMsg("R2SW7: " + R2SW(r, 0, 7))
    call DebugMsg("R2SW8: " + R2SW(r, 0, 8))
    call DebugMsg("R2SW9: " + R2SW(r, 0, 9))
    call DebugMsg("R2I: " + I2S(r2i))
    call DebugMsg("R2Idown: " + I2S(r2idown))
    call DebugMsg("R2Iup: " + I2S(r2iup) + "\n")
// по результату этого теста я не нашёл разницы между R2I() и своей R2Idown(), только нашёл ошибку при использовании == в R2Idown. При каких значениях будет разница между R2I() и своей R2Idown()?
Test 2
function R2SX takes real r returns string
    return R2SW(r, 0, -1)
endfunction

...
    local integer a = 0
    local real r1 = 1.
    local real r2 = 1.
    local real r3 = 1.
    local real r4 = 1.
    local real r5 = 1.
    local real r6 = 1.
    loop
        set r1 = r1 * 1.075
        set r2 = r2 + r2 * .075
        set r3 = 1.075 * r3
        set r4 = r4 * 0.075 + r4
        set r5 = 0.075 * r5 + r5
        set r6 = r6 + 0.075 * r6
        set a = a + 1
        exitwhen a == 10
    endloop
    call DebugMsg("1: " + R2SX(r1)) // 2.061029
    call DebugMsg("2: " + R2SX(r2)) // 2.061031
    call DebugMsg("3: " + R2SX(r3)) // 2.061029
    call DebugMsg("4: " + R2SX(r4)) // 2.061031
    call DebugMsg("5: " + R2SX(r5)) // 2.061031
    call DebugMsg("6: " + R2SX(r6)) // 2.061031
0
18
6 лет назад
Отредактирован Hodor
0
PT153:
Это не так, я только что тестировал
Ну это ты протестировал через форматированную строку, на деле же не должно быть такого. Любое число с плавающей запятой (в jass) у которого больше 4 знаков после запятой - округляется до 4 знаков
0
28
6 лет назад
Отредактирован PT153
0
Любое число с плавающей запятой (в jass) у которого больше 4 знаков после запятой - округляется до 4 знаков
Откуда такая информация? Просто Тест 2 говорит об обратном: в случае сложения и умножения вышла точность в 6 цифр после запятой. Также константы bj_PI и bj_E имеют 5 знаков после запятой.
Мне и 4-х цифр после запятой хватит, да и вопрос не в этом, но источник информации хочется узнать.
0
18
6 лет назад
0
PT153 насчет округления - через DebugMsg тестил)
А насчет 4 чисел после запятой - отсюда xgm.guru/p/wc3/w3datatypes
Из строчки "Константно может быть задан в виде числа с точкой (1.2345)"
0
28
6 лет назад
0
UrsaBoss, спасибо за статью, а вот что я выяснил своими тестами:
  1. R2SW(r, 0, -1) возвращает столько знаков после запятой, сколько есть (до 6).
  2. R2I(9.999999) = 9, если бы округлялось после 4-х знаков, то ответ был бы 10.
  3. R2I(9.9999999) и далее выдаёт 10.
  4. R2I(9.9999998) = 9.
Судя по статье, real == float, у которого всего 7.22 десятичных разряда, то есть округление происходит не всегда после 4-го знака за запятой.
0
30
6 лет назад
Отредактирован Clamp
0
0
23
6 лет назад
0
не проще добавить 0.5 или отнимать
2
20
6 лет назад
2
PT153:
UrsaBoss, спасибо за статью, а вот что я выяснил своими тестами:
  1. R2SW(r, 0, -1) возвращает столько знаков после запятой, сколько есть (до 6).
  2. R2I(9.999999) = 9, если бы округлялось после 4-х знаков, то ответ был бы 10.
  3. R2I(9.9999999) и далее выдаёт 10.
  4. R2I(9.9999998) = 9.
Судя по статье, real == float, у которого всего 7.22 десятичных разряда, то есть округление происходит не всегда после 4-го знака за запятой.
Просто близы решили что высокая точность не нужна
0
23
6 лет назад
0
и кстати делай на int так лучше например у мя 0.0505 это как 505 int и проблем нет...
то есть 505/10000 = 0.0505
0
18
6 лет назад
0
pro100master:
и кстати делай на int так лучше например у мя 0.0505 это как 505 int и проблем нет...
то есть 505/10000 = 0.0505
не очень удобно если делать дофига вычислений
+ это лишняя нагрузка, кому то покажется что это не нагрузка, но всё равно лишнее
0
23
6 лет назад
0
UrsaBoss, скажи зачем вам столько байтов... для процента вполне 10000 int максимум как во всех популярных играх к примеру l2 имеет 1000000 int рандом
2
29
6 лет назад
2
0
28
6 лет назад
Отредактирован PT153
0
Clamp:
Статью уже кидали, ответа на вопрос там нет.
Давно видел эту статейку на HIVE, думал, что её уже давно кинут сюда)
Там и есть ответы на интересующие меня вопросы.
Вот тут ещё об этом.
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.