#java #математика
Необходимо сделать систему балансирующую три положительных переменных.
Например, треугольник телосложения из Fallout 4.
Необходимо получить что-то вроде:
class BalanceTriangle() {
float a = 0.33;
float b = 0.33;
float c = 0.33;
static float sum = 0.99;
void AddA(float value) {
...
}
}
AddA(0.2f); => [0.53f, 0.23f, 0.23f]
Я пробовал простейший вариант
void AddA() {
a += value;
b -= value/2;
c -= value/2;
}
который успешно срабатывает первый раз, но после нескольких манипуляций одна из переменных
может стать отрицательной, что недопустимо.
Тогда я попробовал сбрасывать лишнее вычитание на соседнюю переменную:
void AddA() {
a += value;
if (b - value > 0) {
b -= value/2;
}
else {
float rem = (value/2)-b;
b = 0;
c -= rem;
}
if (c - value > 0) {
c -= value/2;
}
else {
float rem = (value/2)-b;
c = 0;
b -= rem;
}
}
Но в таком случае сумма по неизвестной причине меняется, а при добавлении операций
на каждую переменную всё это выглядит отвратительно.
Подскажите решение задачи.
Ответы
Ответ 1
Раз у Вас уже есть наглядное представление в виде треугольника - то и используйте точку внутри треугольника и её барицентрические координаты В английской вики есть формулы для расчёта этих координат из декартовыхОтвет 2
Нарисуйте по другому картину. Трехмерная система координат. Из центра постройте сферу радиусом 1. Постройте куб со координатами проходящими через (0,0,0) и (1,1,1). Часть сферы которая внутри куба - это и есть поверхность возможных решений. Ну а далее математика из школы. Берете уравнение сферы - одна координата вам известна. То что все координаты положительны - тоже. Неизвестны оставшиеся две координаты. Тут уж есть возможность для творчества - зависит от того как вы захотите распределять изменения между ними. Короче говоря все сведется к решению квадратного уравненияОтвет 3
Сохранить не только сумму a+b+c, но и пропорции между величинами b и c можно так: Индекс "0" соответствует текущим значениям, "1" - новым. Например, (0.44, 0.33, 0.22) →(0.64, 0.21, 0.14).Ответ 4
К сожалению, знаний математики не хватило, чтобы реализовать предложенный товарищем MBo вариант, но в итоге всё решилось проще. Сначала я реализовал функцию Set, которая присваивает a определенное значение. Это значение вычитается из необходимой суммы всех параметров, полученное число - остаток, который необходимо распределить между b и c. (rem) Для равномерного изменения я получаю отношение b к оригинальной сумме b+c и аналогично отношение c. (ratio1 и ratio2) Затем из ранее полученного остатка я нахожу необходимую часть, применив отношения. В итоге сумма остаётся неизменна, а части меняются пропорционально оригинальным значениям. static float sum = 0.99; static float maxVal = 0.97; void SetA (float value) { if (value >= 0 && value <= maxValue) { // находим остаток от присваивания, // который должен распределиться между b и c float rem = sum - value; // находим отношение b к сумме b и c, аналогично для c float ratio1 = b/(sum-a); float ratio2 = c/(sum-a); // получаем новые значения пропорциональные оригинальным b = rem * ratio1; c = rem * ratio2; a = value; } } Другие операции на основе этой реализовать не сложно: void AddA (float value) { SetA(a+value); } Результаты: SetA(0.5f); => Sum: 0.99 Params:0.5/0.245/0.245 AddB(0.2f); => Sum: 0.99 Params:0.36577177/0.445/0.17922819 SetC(0.3f); => Sum: 0.99 Params:0.31128675/0.37871325/0.3
Комментариев нет:
Отправить комментарий