Почему деление числа с плавающей точкой на целое число возвращает 0.0? - PullRequest
40 голосов
/ 23 сентября 2010

Так что, если у меня есть диапазон чисел '0 - 1024', и я хочу привести их к '0 - 255', математика будет диктовать деление ввода на максимум, на котором будет вход (1024 в этом случае) что даст мне число от 0,0 до 1,0. затем умножьте это на диапазон назначения, (255).

Что я и хочу сделать!

Но по какой-то причине в Java (с использованием Processing) всегда будет возвращаться значение 0.

Код будет таким же простым, как этот

float scale;
scale = (n/1024) * 255;

Но я просто получаю 0.0. Я пробовал двойной и инт. все безрезультатно. ПОЧЕМУ!?

Ответы [ 6 ]

73 голосов
/ 23 сентября 2010

Это потому, что вы делаете целочисленное деление.

Разделите на двойное число или число с плавающей точкой, и это будет работать:

double scale = ( n / 1024.0 ) * 255 ;

Или, если хотите, как поплавок,

float scale = ( n / 1024.0f ) * 255 ;
19 голосов
/ 23 сентября 2010

n / 1024 равно целочисленное деление , что дает целое число (т. Е. 0 в данном случае).

Вместо этого используйте n / 1024.0.

7 голосов
/ 23 сентября 2010

Полагаю, 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. Вы все равно будете получать только целочисленные ответы, поэтому вы потеряете все десятичные точки в ответах.

2 голосов
/ 23 сентября 2010

другие уже дали отличные ответы.Если вы хотите, чтобы ваша шкала была целым числом (что имеет смысл, если ваш 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();
}

Вы не переполните никакие целые таким образом,хотя я признаю, что это немного многословно

Редактировать:

В основном то же самое, но менее неуклюже (хотя для очень больших чисел вы можете столкнуться с некоторыми ошибками прецизионности)

int scale(int value, int old_max, int new_max){
  double factor = (double) new_max / (double) old_max;
  return factor * value;
}
2 голосов
/ 23 сентября 2010

В вашем случае n/1024 приводит к 0, поскольку вы делаете целочисленное деление. Чтобы преодолеть это, вы можете разыграть n до float. Это даст вам результат между 0.0 и 1.0, затем вы умножите на 255 и приведете результат обратно к целому числу. Также вам нужно объявить scale как int

int scale;
int n = 80; 
scale = (int)(((float)n/1024) * 255);
2 голосов
/ 23 сентября 2010

Вы должны автоматически привести n к числу с плавающей запятой с помощью умножения FIRST, в противном случае вы выполняете целочисленную операцию, а затем приводите результат вместо операции между числами с плавающей запятой.

float scale;
scale = n * 1.0 / 1024 * 255;
...