Заметил, что данные функции дают разные ответы при 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, думал, что её уже давно кинут сюда)
Там и есть ответы на интересующие меня вопросы.
Вот тут ещё об этом.
`
ОЖИДАНИЕ РЕКЛАМЫ...
23
Похожие вопросы:

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

20
Коротко: математические операции с числами с плавающей запятой с разным числом знаков (после запятой - точно, по идее и до должно учитываться, но тут не уверен... 1.+99.=100.?) порождают погрешность. Так, 0,02+0,1 != 0,12.
В вц3 следует сравнивать с диапазоном. x <= z and x >= y. Либо с R2I(x * 10^y)
Подробнее можно прочитать, например, на хабре
18
Внутри функции 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
28
Ребята, а вы читали вопрос, смотрели функции? Потому что ваши ответы никак не отвечают на вопросы.
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
18
PT153:
Это не так, я только что тестировал
Ну это ты протестировал через форматированную строку, на деле же не должно быть такого. Любое число с плавающей запятой (в jass) у которого больше 4 знаков после запятой - округляется до 4 знаков
28
Любое число с плавающей запятой (в jass) у которого больше 4 знаков после запятой - округляется до 4 знаков
Откуда такая информация? Просто Тест 2 говорит об обратном: в случае сложения и умножения вышла точность в 6 цифр после запятой. Также константы bj_PI и bj_E имеют 5 знаков после запятой.
Мне и 4-х цифр после запятой хватит, да и вопрос не в этом, но источник информации хочется узнать.
18
PT153 насчет округления - через DebugMsg тестил)
А насчет 4 чисел после запятой - отсюда xgm.guru/p/wc3/w3datatypes
Из строчки "Константно может быть задан в виде числа с точкой (1.2345)"
28
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-го знака за запятой.
20
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-го знака за запятой.
Просто близы решили что высокая точность не нужна
22
и кстати делай на int так лучше например у мя 0.0505 это как 505 int и проблем нет...
то есть 505/10000 = 0.0505
18
pro100master:
и кстати делай на int так лучше например у мя 0.0505 это как 505 int и проблем нет...
то есть 505/10000 = 0.0505
не очень удобно если делать дофига вычислений
+ это лишняя нагрузка, кому то покажется что это не нагрузка, но всё равно лишнее
22
UrsaBoss, скажи зачем вам столько байтов... для процента вполне 10000 int максимум как во всех популярных играх к примеру l2 имеет 1000000 int рандом
28
Clamp:
Статью уже кидали, ответа на вопрос там нет.
Давно видел эту статейку на HIVE, думал, что её уже давно кинут сюда)
Там и есть ответы на интересующие меня вопросы.
Вот тут ещё об этом.
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.