Ответ 1
Это потому, что вы выполняете целочисленное деление.
Разделите двойным или поплавком, и он будет работать:
double scale = ( n / 1024.0 ) * 255 ;
Или, если вы хотите, чтобы это было как float,
float scale = ( n / 1024.0f ) * 255 ;
Итак, если у меня есть диапазон чисел "0 - 1024", и я хочу привести их в "0 - 255", математика будет диктовать разделить вход по максимальному значению ввода (в этом случае 1024) который даст мне число от 0.0 до 1.0. затем умножьте его на диапазон назначения (255).
Вот что я хочу делать!
Но по какой-то причине в Java (с использованием обработки) он всегда будет возвращать значение 0.
Код будет таким же простым, как этот
float scale;
scale = (n/1024) * 255;
Но я просто получаю 0.0. Я попробовал double и int. все безрезультатно. ПОЧЕМУ!?
Это потому, что вы выполняете целочисленное деление.
Разделите двойным или поплавком, и он будет работать:
double scale = ( n / 1024.0 ) * 255 ;
Или, если вы хотите, чтобы это было как float,
float scale = ( n / 1024.0f ) * 255 ;
n/1024 - целочисленное деление, которое дает целое число (то есть 0 в этом случае).
Используйте n / 1024.0
вместо этого.
Я предполагаю, что n
является int
. Поскольку константы 1024 и 255 оба int
, все вычисления правой стороны выполняются с целочисленной арифметикой. Значение результата n/1024
усекается до целочисленного значения перед умножением на 255
.
Любая из этих модификаций сделает вычисления корректными:
scale = n / 1024.0 * 255.0; // Use double constants.
scale = (double) n / 1024 * 255; // Convert n to a double.
scale = n * 255 / 1024; // Multiply before dividing.
Последний использует целочисленную математику, но переключение порядка операций означает, что вы не получите нежелательное усечение до 0. Вы все равно получите только целые ответы, так что вы потеряете десятичные точки в ответах.
Вы должны автоблокировать n для float с помощью умножения FIRST, иначе вы выполняете операцию с целым числом и затем выполняете результат вместо выполнения операции между поплавками.
float scale;
scale = n * 1.0 / 1024 * 255;
В вашем случае n/1024
результат равен 0, поскольку вы выполняете целочисленное деление. Чтобы преодолеть это, вы можете применить n
к float
. Это даст вам результат между 0.0
и 1.0
, после чего вы умножаетесь на 255
и возвращаете результат в целое число. Также вам нужно объявить scale
как int
int scale;
int n = 80;
scale = (int)(((float)n/1024) * 255);
другие уже дали большие ответы. Если вы хотите, чтобы ваш масштаб был целым (что имеет смысл, если ваш n уже является целым числом), вы можете сделать
int scale = ((255 * n)/1024);
Обратите внимание, что вы не столкнетесь с какими-либо проблемами с этим, если это числа, так как n * 255 всегда будет соответствовать int, когда максимум n = 1024.
более гибким будет
int scale(int value, int old_max, int new_max){
java.math.BigInteger big_value = java.math.BigInteger.valueOf(value);
java.math.BigInteger big_old_max = java.math.BigInteger.valueOf(old_max);
java.math.BigInteger big_new_max = java.math.BigInteger.valueOf(new_max);
java.math.BigInteger mult = big_value.multiply(big_old_max);
return (int) mult.devide(big_new_max).doubleValue();
}
Вы не будете переполнять никакие ints таким образом, хотя я признаю, что это немного подробный
Edit:
В основном то же самое, но менее неуклюже (хотя для очень больших чисел вы можете столкнуться с некоторыми ошибками прецессии)
int scale(int value, int old_max, int new_max){
double factor = (double) new_max / (double) old_max;
return factor * value;
}