Есть у кого эффективный стабильный вариант? Максимум к чему пришел я:
		I2R( R2I( r * 100000000.) ) * 0.00000001
Умножение на 10^-8 дает эквивалентный результат делению на 10^8.
Использование степеней менее чем 8я значительно увеличивает погрешность.
Использование приведенной формулы не исключает наращивание погрешности.
Хотя, судя по всему, использование этой формулы увеличивает погрешность даже при 10^8.

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

Real в WarCraft работает абсолютно также, как float в C++ (фактически, это он и есть).

Математическое округление в принципе лучше делать по-другому:
    #define fround = M_RoundFloat
    #define round  = M_Round

    int M_Round(float number) {
        if (number > 0) {
            return R2I(number + 0.5);
        }
        if (number < 0) {
            return R2I(number - 0.5);
        }
        return 0;
    }

    float M_RoundFloat(float number) {
        if (number > 0.0) {
            return I2R(R2I(number + 0.5));
        }
        if (number < 0.0) {
            return I2R(R2I(number - 0.5));
        }
        return 0.0;
    }
Так оно будет отрабатывать гарантировано верно и без тяжёлых операций.

Давно хотел куда-нибудь прилепить этот файлик, но всё не находилось случая, наконец-то!
Загруженные файлы
1
20
7 лет назад
Отредактирован Diaboliko
1
Гораздо более стабильный результат дают вычисления между преобразованными в интегеры флоатами(R2I(r*10^8)), правда погрешность все-равно появляется когда наступает время умножать на 10^-8. Использование степени меньшей, чем 8я, увеличивает погрешность. Использование непосредственно восьмой степени, судя по тестам, исключает наращивание погрешности(небольшая погрешность появляется после упомянутого умножения на 10^-8)
Только вот этот метод не подходит.
6
30
7 лет назад
Отредактирован Clamp
6
Real в WarCraft работает абсолютно также, как float в C++ (фактически, это он и есть).

Математическое округление в принципе лучше делать по-другому:
    #define fround = M_RoundFloat
    #define round  = M_Round

    int M_Round(float number) {
        if (number > 0) {
            return R2I(number + 0.5);
        }
        if (number < 0) {
            return R2I(number - 0.5);
        }
        return 0;
    }

    float M_RoundFloat(float number) {
        if (number > 0.0) {
            return I2R(R2I(number + 0.5));
        }
        if (number < 0.0) {
            return I2R(R2I(number - 0.5));
        }
        return 0.0;
    }
Так оно будет отрабатывать гарантировано верно и без тяжёлых операций.

Давно хотел куда-нибудь прилепить этот файлик, но всё не находилось случая, наконец-то!
Загруженные файлы
Принятый ответ
0
20
7 лет назад
0
Действительно, запамятовал я про +0.5. Все заработало как надо. Пока что... :)
Треп не по делу
    int M_Round(int number) {
        if (number > 0) {
            return R2I(number + 0.5);
        }
        if (number < 0) {
            return R2I(number - 0.5);
        }
        return 0;
    }
Ятп ты передаешь инт и округляешь его до самого себя?
0
26
7 лет назад
Отредактирован Hanabishi
0
Непонятна суть вопроса, что за погрешность и зачем какие-то степени. Если нужно просто число округлить, то это банальнейшая операция. В ответе выше правильно написано, только с типами какая-то муть, надо вот так:
int Round(real number){
    if(number > .0){
        return R2I(number + .5);
    }
    if (number < .0){
        return R2I(number - .5);
    }
    return 0;
}
0
30
7 лет назад
Отредактирован Clamp
0
Оффтоп
Треп не по делу
Я полагал, что это останется незамеченным и будет скопипасчено =)
В оригинале принимает не инт, а флоат, разумеется, выправил пост, раз уж он как ответ закреплён.

Пока что...
Всегда.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.