views:

219

answers:

6

Hello helpers!

So if I have a range of numbers '0 - 1024' and I want to bring them into '0 - 255', the maths would dictate to divide the input by the maximum the input will be (1024 in this case) which will give me a number between 0.0 - 1.0. then multiply that by the destination range, (255).

Which is what I want to do!

But for some reason in Java (using Processing) It will always return a value of 0.

The code would be as simple as this

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

But I just get 0.0. I've tried double and int. all to no avail. WHY!?

+13  A: 

It's because you're doing integer division.

Divide by a double or a float, and it will work:

double scale = ( n / 1024.0 ) * 255 ;

Or, if you want it as a float,

float scale = ( n / 1024.0f ) * 255 ;
tim_yates
Thank you so much for the answer! :)
Arif Driessen
+5  A: 

n / 1024 is integer division, which yields an integer (ie. 0 in this case).

Use n / 1024.0 instead.

Alexandre C.
+1 because it is better than my answer :)
Agos
Thank you so much for the answer! :)
Arif Driessen
A: 

You should auto-cast n to float by means of a multiplication FIRST, otherwise you're doing an integer operation and then casting the result, instead of doing the operation between floats.

float scale;
scale = n * 1.0 / 1024 * 255;
Agos
+1  A: 

I presume n is an int. Because the constants 1024 and 255 are both ints all the right-hand side calculations are being done with integer arithmetic. Meaning the result of n/1024 is being truncated to a integral value before being multiplied by 255.

Any of these modifications will make the calculations work correctly:

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.

The last one uses integer math still but switching the order of operations means you won't get the undesired truncation to 0. You'll still only get integer answers though, so you'll lose any decimal points in the answers.

John Kugelman
Thank you so much for the answer! :)
Arif Driessen
+1  A: 

In your case n/1024 results in 0 as you are doing integer division. To overcome this you can cast n to float. This will give you a result between 0.0 and 1.0 next you multiply with 255 and cast the result back to integer. Also you need to declare scale as int

int scale;
int n = 80; 
scale = (int)(((float)n/1024) * 255);
codaddict
@Downvoter: Care to explain ?
codaddict
@codaddict: probably a parenthephobe. Cancelled with a upvote.
GregS
+2  A: 

others have given great answers already. In case you want your scale to be an integer (which makes sense if your n is an integer already), you could do

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

Note that you won't hit any problems with this as long as these are the numbers, since n * 255 will always fit in an int when the maximum n = 1024.

more flexible would be

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();
}

You won't overflow any ints this way, though I admit this is a bit verbose

Edit:

Basicly the same, but less clunky (though for very high numbers you might run into some precission errors)

int scale(int value, int old_max, int new_max){
  double factor = (double) new_max / (double) old_max;
  return factor * value;
}
Martijn
Heh, this is why I hate BigInteger and BigDecimal.
Tony Ennis