Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert number from double to int without rounding?

Tags:

java

I want to calculate how many columns can fit into container. First I calculate how many columns can fit in, then I calculate number of margins for them. After that I check if they will fit in with margins, if no - reduce amount of columns by one. Code:

int columnMargin = 50;
double result = columnContainerHBox/minimalColumnWidth;
int columnCount = (int) result; // here's the problem
int numberOfMargins = columnCount - 1;
double finalCount = columnContainerHBox/minimalColumnWidth*columnCount+columnMargin*numberOfMargins;
if(finalCount<1){
    columnCount--;
}

The problem is that I don't know how to convert from double to int without rounding number. I just need to get rid of all numbers after decimal. I already tried (int) double, (int)Math.floor(double) and new DecimalFormat('#').format(double). As a double I took 1.99999999999999999999. All above was converting it to 2. Desirable result - 1;

My double is going to be completely random. It can be 1.0, 1.9999999999, 2.45, 3.5959547324 etc.

What I need is to get a whole part and completely discard everything after decimal.

like image 339
Alyona Avatar asked Mar 06 '23 03:03

Alyona


1 Answers

You do it by casting to int, as you're already doing in the code you've presented as an attempt.

I understand that you feel unsatisfied because you think you have found a case when your attempt will round the value instead of dropping the decimal part.

You have tried with value 1.99999999999999999999 and you've noticed that casting it to int produces an int of value 2. You concluded from there that casting is not just dropping the decimal part, it is rounding to the closest whole number 2.

Your conclusion is incorrect. The number 2 is not obtained as a result of casting to int. The number 2 is a result of the compiler parsing the written literal value 1.99999999999999999999. doubles don't have infinite precision. That means you can't write as many decimals as you want and expect it to be correctly kept in a double value. doubles only offer approximations of what you're asking. So when you type the literal value 1.99999999999999999999, the compiler knows that it is incapable to represent that value exactly, and instead it will take it as the closest value that can be represented in a double.

And the representable value closest to 1.99999999999999999999 is 2. As far as the Java compiler is concerned, these two numbers are one and the same.

So when you write:

double d = 1.99999999999999999999d;

the Java compiler treats it completely equivalent to:

double d = 2d;

You'll notice that at this point, you have yet to do any attempt to drop the decimals and only keep the whole part. You've only declared a value for your double, and as far as you're concerned this value could very well have a decimal part.

Your attempt to only keep the whole value only happens when you do:

int i = (int)d;

and here the decimals are dropped and your int contains only the whole part of what the double value contained.

However, in your example, since your double value was 2.0, then taking the whole part of it is 2. That's not rounding. That's not anything else than keeping only the whole part.

The correct way to drop decimals and only keep the whole part, is to cast to int.

(If it is important to you to be able to manipulate values such as 1.99999999999999999999 and have them not be the same as 2.0, then you cannot use doubles. They don't have sufficient precision. You should use BigDecimal, with new BigDecimal("1.99999999999999999999"). The constructor must be called with a String rather than a floating-point value, since floating-point values are unable to represent the value you want.)

like image 70
kumesana Avatar answered Mar 14 '23 19:03

kumesana