#java #double #rounding #logarithm #significance
#java #двойной #округление #логарифм #значение
Вопрос:
Недавно, разрабатывая калькулятор для упрощения игры (reactor idle), я столкнулся с одной постоянной проблемой. Проблема заключалась в том, что когда вводимое число в графическом интерфейсе изменялось на число между определенными границами, оно немедленно возвращалось к числу под ним при нажатии enter, иногда это даже повторялось, если вы снова нажимали enter.
Я полагал, что одна часть кода каким-то образом несовместима с другой частью, хотя математика, стоящая за ней, была надежной.
Первая часть кода вычисляет тепло, выделяемое тепловыми элементами, вторая пересчитывает обновления, необходимые в каждом компоненте для обработки этого тепла. Итак, скажем, обновление, в котором вы сейчас находитесь, находится прямо на границе рабочего и конфликтующего кода, если вы затем увеличите обновление, оно немедленно вернется. Поскольку первый фрагмент кода вычисляет тепло, а второй решает, что вы могли бы обойтись одним меньшим обновлением, чтобы по-прежнему достичь этого тепла.
Соответствующие фрагменты кода:
double insulationMultiplier = 1 insulationPerCell * (insulationUpgrades 1) * INSULATION_HEAT_MODIFIER;
double upgradeMultiplier = Math.pow(Cell.HEAT_MULTIPLIER, cellUpgrades);
this.heat = cells * insulationMultiplier * upgradeMultiplier * cell.heat * (1 0x4p-50d); //???
//avoid trouble when calculating cellUpgrades
this.calculate(START_FROM_HEAT);
double insulationMultiplier = 1 insulationPerCell * (insulationUpgrades 1) * INSULATION_HEAT_MODIFIER;
double circulatorMultiplier = circulators ? CIRCULATOR_HEAT_MODIFIER * Math.pow(CIRCULATOR_HEAT_MULTIPLIER, circulatorUpgrades) : 1;
cellUpgrades = (int) ((Math.log(this.heat) - Math.log(insulationMultiplier * cells * cell.heat)) / Math.log(Cell.HEAT_MULTIPLIER));
Как вы можете видеть, я решил проблему, умножив тепло, рассчитанное в первой части, на 1 0x4p-50d
, это делается для того, чтобы тепло регулировалось ровно настолько, чтобы вторая часть алгоритма не округляла обновление снова и как можно меньше, чтобы избежать отображения сильно отличающегося значения тепла.
Та же проблема возникает в параллельном фрагменте кода, относящемся к двум другим компонентам, однако в гораздо большем масштабе, так что он перескакивает сразу на несколько чисел. Я бы предпочел не решать его так же, как я сделал для первого компонента, поскольку это, вероятно, столкнется с другими вещами, в свою очередь.
Есть ли более строгий, так сказать, способ решения этой проблемы?
Заранее спасибо.
Комментарии:
1. Я предполагаю, что вы не работаете на пределе точности
double
, если да, то вам следует использовать другую стратегию. Либо используйте BigDecimal, либо используйте формулу, в которой нет этой проблемы.2. Я предполагаю, что
* (1 0x4p-50d)
это работает как фактор выдумки для небольшой ошибки представления. Я предлагаю сохранитьlogOfHeat
вместоheat
значения.