Concatenating a double in a string truncates - java

For a variable double spread = 0.135; I'm writing
"" + Math.round(spread * 10000) / 100 + "%"
This is attempting to round to 1 basis point. (100 basis points = 1 %).
But it doesn't include any decimal part.
Why?

This is yet another variant of integer division truncates; albeit slightly more deeply buried than normal.
Math.round(spread * 10000) returns an long. Dividing that by 100 will truncate the result to a long.
Your fix? Use 100.0 as the divisor. Then the expression is computed in floating point.

When you divide a long by an int you get a long which is a whole number. The simple solution is to divide by a double. Try
Math.round(spread * 10000) / 100.0 + "%"
or
Math.round(spread * 1e4) / 1e2 + "%"

Round() returns a long. The div operation is thus a long value.

Related

how to get number of micro seconds in a day

I want to get the number of micro seconds in a day
so I tried as per below
long microDay = 24 * 60 * 60 * 1000 * 1000;
for which I am expecting value as 86400000000 but when I print it
System.out.println(microDay);
The value is 500654080
After spending 3 hours and breaking my head to know the reason,final I found that java think 24,60 and 1000 as int values and int*int =int but the maximum value of int is 2147483647 so it cant store 86400000000 and hence it the output is 500654080 (but I am not sure)
In the second case I wanted to calculate miliseconds in a day and the formula goes like this
long miliDay = 24 * 60 * 60 * 1000;
System.out.println(miliDay );
output 86400000
now when I did
System.out.println(microDay/ miliDay);
output 5
but when I tried this in a calculator 500654080/86400000= 5.794607407407407
why there is different in result?
You're performing 32-bit integer arithmetic, as every operand in 24 * 60 * 60 * 1000 * 1000 is an int... but the result is bigger than Integer.MAX_VALUE, so it's overflowing (just as you suspected). (This is actually happening at compile-time in this case, because it's a compile-time constant, but the effect is the same as if it happened at execution time.)
Effectively, each operation is truncated to 32 bits. As it happens, only the final multiplication by 1000 takes the result over 231 - 86400000 is fine.
86400000000 in binary is:
1010000011101110101110110000000000000
^
\- Bit 33
So after overflow, we just chop any leading bits until we've got 32:
00011101110101110110000000000000
And that value is 500654080.
Just use long instead, e.g.
long microDay = 24L * 60L * 60L * 1000L * 1000L;
(You definitely don't need all those constants to be of type long, but being consistent means it's obvious that all the operations will be performed using 64-bit arithmetic, with no need to consider associativity etc.)
A better approach, however, would be to use TimeUnit:
long microDay = TimeUnit.DAYS.toMicroseconds(1);
As for the division part, you're performing integer division - so the result is the integer part, rounded towards 0. If you want floating point arithmetic, you need to cast one of the operands to float or double... although if you start off with the right values, of course, you should get an exact integer anyway (1000).
For the first part, put a "L" at the end of one (or more) of the constants and Java will then use long arithmetic. e.g.
long microDay = 24L * 60 * 60 * 1000 * 1000;
Addendum: Why did you get 500654080?
86400000000 decimal = 141DD76000 hex.
But, the integer only holds 32 bits, which is 8 "digits". So you lose the leading 14 and retain 1DD76000 hex.
Converting that to decimal gives 500654080.
As for the division, when you divide ints by ints (or longs by longs) Java returns the result as an int or long, so it has to truncate (or round, but Java chose to truncate) the result to 5 instead of 5.7946... Force it to do floating point arithmetic by casting one of the values to a double, e.g.
System.out.println((double)microDay/ miliDay);
When you are performing a division between 2 integers, the results are an integer. The results of the arithmetic operation will be rounded down to the nearest integer.
int i = 5 / 2; // 2.5 is rounded down to 2
if you want the output to include the decimal precision, you will need to use a different primitive data type and explicitly specify your operands to be doubles.
double j = 5 / 2; //2.0 as 5 / 2 yields and integer 2 which will be casted to a double
double j = 5 / 2.0; //2.5 explicit usage of a double will tell the compiler to return the results in double
The nuclear operations inside
long microDay = 24 * 60 * 60 * 1000 * 1000;
are all Integers specific. Max value of Integer object is 2147483647. Which exceeds the original output which is long.
Simply specifying long to variable doesn't mean all operations using [ * ] will be done using long instances. All operations done in assignment became sort of truncated.
Solution is to explicitly specify that all nuclear operations should happen over long instance and not int instances.
long microDay = 24L * 60L * 60L * 1000L * 1000L;

value to the next thousand instead of nearest thousand

Sorry im new to java, currently i wanted to code the value to next thousand instead of nearest thousand. But i have no ideas how to do it. I tried Math.round but it's for roundest. Please guide me, any help would be appreciated .
Expected output that i looking for :
example 1) if the place values less than 999, it will direct change to 1000
May i know how can i code the math formula for this ?
You can use Math.ceil for this.
// A quick code example :)
int val = 1400;
val = (int) (Math.ceil(val / 1000.0) * 1000);
You need to write some custom code as follow
int leftdigit=value/1000;
int nextthousand=(leftdigit+1)*1000;
Here Kindly note Math.ceil returns double so you should use it properly as stated below as for integer value it won't work properly and integer division will be performed.
double data = 1100;
data = Math.ceil(data / 1000) * 1000;
System.out.println(data);
OUTPUT
2000.0
Conversion from integers to floats leads to chaos, as for the same bit size, float mantissa length will always be smaller than integer size (IEEE-754 float mantissa is 23 bits vs 31 bits for the integer). Converting a large integer to float back and forth will not give the same integer after the conversion.
So here using Math.ceil() may work for integers or small long ints, but will break for large long values (63 bits).
Better use the following code (only works for value > 0):
int ii = ((i - 1) / 1000 + 1) * 1000;
or for long int version:
long ii = ((i - 1) / 1000 + 1) * 1000;
Does not unnecessarily overflow, keep precision even for large values, and probably way faster!
Addenda
As an example, the following java code:
int largeint = Integer.MAX_VALUE - 63;
float fl = (float)largeint;
int largeint2 = (int)fl;
System.out.println(largeint);
System.out.println(largeint2);
Print:
2147483584
2147483647

Positive division, negative result in Java

I'm really puzzled by this. I'm dividing two positive numbers and getting a negative result (I'm using Java).
long hour = 92233720368L / (3600 * 1000000 );
I got as result -132.
But if I divide them as two long numbers, I get the right result:
long hour1 = 92233720368L / (3600000000L );
Then I get as result: 25
I'm wondering why it occurs...
Thank you in advance! :)
You must add L at the end of 3600 or 1000000:
Example:
long hour = 92233720368L / (3600 * 1000000L );
Here's what's hapenning:
System.out.println(3600 * 1000000); // Gives -694967296 because it exceeds the max limit of an integer size. So 92233720368L / -694967296 = -132
That's exactly what's happening in your division, the dominator is an integer and is considered as negative number for the reason I stated above. So in order to consider the multiplication result of type long you should add L after 3600 or after 1000000
It interprets 3600 and 10000000 as type int which cannot hold enough information to represent their product, and so you get a different number. You'd have to declare them both as type long to get the correct result.

How to make one digit after decimal point?

Searching how to make two digit after decimal point as below
$ = (double) (((int)($ * 100)) / 100.0);
Anyone can help to how to make "one digit" after decimal point ?
thanks a lot
What about this:
$ = (double) (((int)($ * 10)) / 10.0);
Note: edited after the comment.
If you need java and rounding instead of truncate try this:
import java.lang.Math;
double a;
a = ((double) (round(a*10))) / 10.0;
This will shift left the dot of one position, round to the nearest integer and then shift the dot back to the right one position.
Edited second time:
What you need is still unclear.
If you are fine with truncate as before:
double $=1.24*(double)amount;
$ = (double) (((int)($ * 1000)) / 1000.0);
outelc.setText("ELC(1.24)= " + Double.toString($) + " /pc");
If you need rounding:
double $=1.24*(double)amount;
$ = (double) ((round($ * 1000)) / 1000.0);
outelc.setText("ELC(1.24)= " + Double.toString($) + " /pc");
If you are using doubles to store/calculate currency values, then you will likely find yourself in a world of pain with rounding. Been there, done that, got the scars.
I highly recommend that you use BigDecimal values for ALL currency values, and do not even involve doubles in the instantiation. Always use the String constructor.
See related questions here and here.

Rounding a double

Hey guys, I am trying to round to 3 decimal places.
I used the following code.
this.hours = Round(hours + (mins / 60), 3);
But it's not working.
Where have I gone wrong?
Thanks
You can use this function:
public static double Round(double number, int decimals)
{
double mod = Math.pow(10.0, decimals);
return Math.round(number * mod ) / mod;
}
First thing is that all your variables are int so the result of your division is also an int, so nothing to Round.
Then take a look to: How to round a number to n decimal places in Java
If mins is an integer, then mins / 60 will result in an integer division, which always results in 0.
Try changing from 60 to 60.0 to make sure that the division is treated as a floating point division.
Example:
int hours = 5;
int mins = 7;
// This gives 5.0
System.out.println(Math.round(1000 * (hours + (mins / 60 ))) / 1000.0);
// While this gives the correct value 5.117. (.0 was added)
System.out.println(Math.round(1000 * (hours + (mins / 60.0))) / 1000.0);
if mins is an integer you have to divide through 60.0 to get a floating number which you can round
try using like follow
this.hours = Round(hours + (((double)mins) / 60), 3);
You can't. Doubles don't have decimal places, because they are binary, not decimal. You can convert it to something that does have decimal places, i.e. a base-ten number, e.g. BigDecimal, and adjust the precision, or you can format it for output with the facilities of java.text, e.g. DecimalFormat, or the appropriate System.out.printf() string.

Categories