My code is:
x=new BigDecimal(x.toString()+" "+(new BigDecimal(10).pow(1200)).toString());
I am trying to concat two bigdecimals after converting them to string and then convert them back to bigdecimal.I am doing so because x has a value with a decimal point and multiplying will change its value.It compiles fine but throws a numberformat exception on execution.
My idea was to use the BigDecimal("String x") constructor to convert the string back to BigDecimal.
Note:
(for example)
x=1333.212
and I am converting it to
x=1333.2120000
It's failing to parse because you've got a space in there for no particular reason. Look at the string it's trying to parse, and you'll see it's not a valid number.
If you're just trying to add extra trailing zeroes (your question is very unclear), you should change the scale instead:
x = x.setScale(x.scale() + 1200);
Simple example:
BigDecimal x = new BigDecimal("123.45");
x = x.setScale(x.scale() + 5);
System.out.println(x); // 123.4500000
If you were trying to multiply the value by a power of 10 (as your initial question suggested), there's a much simpler way of doing this, using movePointRight:
x = x.movePointRight(1200);
From the docs:
The BigDecimal returned by this call has value (this × 10n) and scale max(this.scale()-n, 0).
You need to try in this way
BigDecimal result=new
BigDecimal("1333.212123232432543534324243253563453423423242452543535")
.multiply(new BigDecimal("10").pow(1200));
System.out.println(result);
For your Edit:
BigDecimal result=new
BigDecimal("1333.212123232432543534324243253563453423423242452543535")
.multiply(new BigDecimal("10").pow(1200));
System.out.println(result.movePointRight(-1200));
Related
I'm beginning in Java, and could anyone explain me why Java gives me these answers?
I have a very simple class trying to learn how to round a number.
I want 2 decimals
so...
public static void main(String[] args) {
double pi1 = Math.PI;
System.out.println("pi1 = " + pi1);
double p2 ;
p2= Math.round(pi1*100)/100;
//p2= Math.round(pi1*100)
//p2=p2/100;
System.out.println("p2 = " + p2);
}
If I run this result is:
p2 = 3.0
Then I change
//p2= Math.round(pi1*100)/100;
p2 = Math.round(pi1*100);
p2 = p2/100;
Now, result is:
p2 = 3.14
as I wanted
Why with these differences? Why the first option doesn't give me 3.14
I think that I've made a correct code with 1st option.
Please, anyone could tell me why?
These things makes me don't trust Java.
Thank you.
I will assume that you know how integer division works in Java. In short, when both sides of / are integral types, like in 314 / 100, the expression evaluates to an integer too, like 3.
Math.round returns a long, which is an integral type. In your first code, you have the expression Math.round(pi1*100)/100. Math.round(...) returns an integer type, 100 is an integer literal, so integer division occurs.
However, in the second code, you first assigned the result of Math.round to p2. The long returned is implicitly converted to a double first, and stored in p2. You then wrote an expression in p2: p2/100. Here, one of the operands is double, so integer division does not occur.
Therefore, the one liner version that is the same as the second code is:
p2 = ((double)Math.round(pi1*100))/100;
You don't see the double conversion in the second code because it is done implicitly.
A note on rounding
This way rounding doubles should be used if you want to do calculations with the rounded number afterwards. If you just want to display a rounded number as output, you should use String.format, System.out.printf, or DecimalFormat. Read more about these methods here.
No mistake here, it works properly. Method Math.round(double) returns type long.
In your first variant, you receive result long 314 and divide it by 100 and get the result 3, and then assign it back to double.
In your second variant, you receive long result 314 and assign it back to double. Dividing double keeps precision as opposed to dividing long, so you get the correct result of 3.14
There for make p2= Math.round(pi1*100)/100; as
p2= Math.round(pi1*100) / 100.0;
Output -:
pi1 = 3.141592653589793
p2 = 3.14
This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 8 years ago.
If the value is 200.3456, it should be formatted to 200.34.
If it is 200, then it should be 200.00.
Here's an utility that rounds (instead of truncating) a double to specified number of decimal places.
For example:
round(200.3456, 2); // returns 200.35
Original version; watch out with this
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
value = value * factor;
long tmp = Math.round(value);
return (double) tmp / factor;
}
This breaks down badly in corner cases with either a very high number of decimal places (e.g. round(1000.0d, 17)) or large integer part (e.g. round(90080070060.1d, 9)). Thanks to Sloin for pointing this out.
I've been using the above to round "not-too-big" doubles to 2 or 3 decimal places happily for years (for example to clean up time in seconds for logging purposes: 27.987654321987 -> 27.99). But I guess it's best to avoid it, since more reliable ways are readily available, with cleaner code too.
So, use this instead
(Adapted from this answer by Louis Wasserman and this one by Sean Owen.)
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
Note that HALF_UP is the rounding mode "commonly taught at school". Peruse the RoundingMode documentation, if you suspect you need something else such as Bankers’ Rounding.
Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
And in every case
Always remember that floating point representations using float and double are inexact.
For example, consider these expressions:
999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
For exactness, you want to use BigDecimal. And while at it, use the constructor that takes a String, never the one taking double. For instance, try executing this:
System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));
Some excellent further reading on the topic:
Item 48: "Avoid float and double if exact answers are required" in Effective Java (2nd ed) by Joshua Bloch
What Every Programmer Should Know About Floating-Point Arithmetic
If you wanted String formatting instead of (or in addition to) strictly rounding numbers, see the other answers.
Specifically, note that round(200, 0) returns 200.0. If you want to output "200.00", you should first round and then format the result for output (which is perfectly explained in Jesper's answer).
If you just want to print a double with two digits after the decimal point, use something like this:
double value = 200.3456;
System.out.printf("Value: %.2f", value);
If you want to have the result in a String instead of being printed to the console, use String.format() with the same arguments:
String result = String.format("%.2f", value);
Or use class DecimalFormat:
DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
I think this is easier:
double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(time));
System.out.println(time); // 200.35
Note that this will actually do the rounding for you, not just formatting.
The easiest way, would be to do a trick like this;
double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;
if val starts at 200.3456 then it goes to 20034.56 then it gets rounded to 20035 then we divide it to get 200.34.
if you wanted to always round down we could always truncate by casting to an int:
double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;
This technique will work for most cases because for very large doubles (positive or negative) it may overflow. but if you know that your values will be in an appropriate range then this should work for you.
Please use Apache commons math:
Precision.round(10.4567, 2)
function Double round2(Double val) {
return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}
Note the toString()!!!!
This is because BigDecimal converts the exact binary form of the double!!!
These are the various suggested methods and their fail cases.
// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d
Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val)
// By default use half even, works if you change mode to half_up
Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(value));
If you really want the same double, but rounded in the way you want you can use BigDecimal, for example
new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
For two rounding digits. Very simple and you are basically updating the variable instead of just display purposes which DecimalFormat does.
x = Math.floor(x * 100) / 100;
Rounding a double is usually not what one wants. Instead, use String.format() to represent it in the desired format.
In your question, it seems that you want to avoid rounding the numbers as well? I think .format() will round the numbers using half-up, afaik?
so if you want to round, 200.3456 should be 200.35 for a precision of 2. but in your case, if you just want the first 2 and then discard the rest?
You could multiply it by 100 and then cast to an int (or taking the floor of the number), before dividing by 100 again.
200.3456 * 100 = 20034.56;
(int) 20034.56 = 20034;
20034/100.0 = 200.34;
You might have issues with really really big numbers close to the boundary though. In which case converting to a string and substring'ing it would work just as easily.
value = (int)(value * 100 + 0.5) / 100.0;
I am trying to get the digit in the hundredth's place of a double value (second digit after the decimal).
So, for example, if the double value is 48.4569999, I want to get the value 5 using any Math or BigDecimal methods, which is the hundredth's place after decimal.
I have tried the following code:
BigDecimal src = new BigDecimal("48.4569999");
BigDecimal a = src.remainder(BigDecimal.ONE);
System.out.println("a : " + a);
which results in .456999 but I dont want to use any String functions to get to the second digit. Is there any Math or Bigdecimal function to do this please ? Your help is appreciated.
Why not multiply by 100, to push your desired value to the right place, cast to int (to remove anything < 1) and then do % 10, which will give you the remainder (which will be your desired digit).
You may be looking for movePointRight(int).
int a = src.movePointRight(2).remainder(BigDecimal.TEN).intValue();
prints
a : 5
This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 8 years ago.
If the value is 200.3456, it should be formatted to 200.34.
If it is 200, then it should be 200.00.
Here's an utility that rounds (instead of truncating) a double to specified number of decimal places.
For example:
round(200.3456, 2); // returns 200.35
Original version; watch out with this
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
value = value * factor;
long tmp = Math.round(value);
return (double) tmp / factor;
}
This breaks down badly in corner cases with either a very high number of decimal places (e.g. round(1000.0d, 17)) or large integer part (e.g. round(90080070060.1d, 9)). Thanks to Sloin for pointing this out.
I've been using the above to round "not-too-big" doubles to 2 or 3 decimal places happily for years (for example to clean up time in seconds for logging purposes: 27.987654321987 -> 27.99). But I guess it's best to avoid it, since more reliable ways are readily available, with cleaner code too.
So, use this instead
(Adapted from this answer by Louis Wasserman and this one by Sean Owen.)
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
Note that HALF_UP is the rounding mode "commonly taught at school". Peruse the RoundingMode documentation, if you suspect you need something else such as Bankers’ Rounding.
Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
And in every case
Always remember that floating point representations using float and double are inexact.
For example, consider these expressions:
999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
For exactness, you want to use BigDecimal. And while at it, use the constructor that takes a String, never the one taking double. For instance, try executing this:
System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));
Some excellent further reading on the topic:
Item 48: "Avoid float and double if exact answers are required" in Effective Java (2nd ed) by Joshua Bloch
What Every Programmer Should Know About Floating-Point Arithmetic
If you wanted String formatting instead of (or in addition to) strictly rounding numbers, see the other answers.
Specifically, note that round(200, 0) returns 200.0. If you want to output "200.00", you should first round and then format the result for output (which is perfectly explained in Jesper's answer).
If you just want to print a double with two digits after the decimal point, use something like this:
double value = 200.3456;
System.out.printf("Value: %.2f", value);
If you want to have the result in a String instead of being printed to the console, use String.format() with the same arguments:
String result = String.format("%.2f", value);
Or use class DecimalFormat:
DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
I think this is easier:
double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(time));
System.out.println(time); // 200.35
Note that this will actually do the rounding for you, not just formatting.
The easiest way, would be to do a trick like this;
double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;
if val starts at 200.3456 then it goes to 20034.56 then it gets rounded to 20035 then we divide it to get 200.34.
if you wanted to always round down we could always truncate by casting to an int:
double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;
This technique will work for most cases because for very large doubles (positive or negative) it may overflow. but if you know that your values will be in an appropriate range then this should work for you.
Please use Apache commons math:
Precision.round(10.4567, 2)
function Double round2(Double val) {
return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}
Note the toString()!!!!
This is because BigDecimal converts the exact binary form of the double!!!
These are the various suggested methods and their fail cases.
// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d
Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val)
// By default use half even, works if you change mode to half_up
Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(value));
If you really want the same double, but rounded in the way you want you can use BigDecimal, for example
new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
For two rounding digits. Very simple and you are basically updating the variable instead of just display purposes which DecimalFormat does.
x = Math.floor(x * 100) / 100;
Rounding a double is usually not what one wants. Instead, use String.format() to represent it in the desired format.
In your question, it seems that you want to avoid rounding the numbers as well? I think .format() will round the numbers using half-up, afaik?
so if you want to round, 200.3456 should be 200.35 for a precision of 2. but in your case, if you just want the first 2 and then discard the rest?
You could multiply it by 100 and then cast to an int (or taking the floor of the number), before dividing by 100 again.
200.3456 * 100 = 20034.56;
(int) 20034.56 = 20034;
20034/100.0 = 200.34;
You might have issues with really really big numbers close to the boundary though. In which case converting to a string and substring'ing it would work just as easily.
value = (int)(value * 100 + 0.5) / 100.0;
I have few small basic problems :
How to format :
int i = 456;
to give output :
""00000456"
? I've tried %08d but it's not working. Next thing is a problem with conversion and then formatting. I have side and height of triangle, let's say int's 4,7, and 7 is the height. From formula for field we know that F=1/2(a*h). So how to get F as float, with precision up to 10 places ?
float f = a*h;
works fine, but multiplying it by 0.5 gives error and by 1/2 returns 0.
Use NumberFormat class see this or that explanation, the Formatter class or String.format
How to format :
int i = 456; to give output :
"00000456"
System.out.printf("%08d", i) can do the job.
1/2 is an integer expression, it will not be automatically converted to a float.
1/2 should be one of: 1.0f/2.0f, 1.0f/2, 1/2.0f, (float)1/(float)2, (float)1/2, 1/(float)2, float-variable/float-variable, float-variable/int-variable, int-variable/float-variable, ... you get the idea
Should be %.08d instead of %08d, secondly try multiplying by 0.5f instead.
Answer was to use String.format.
String fs = String.format("%08d", this.id);
return fs;