I have int value 40959999. How to convert it to float without rounding into 409599,99?
result of float f = 40959999/100.00f will be 409600.0
Use double instead of float
double d = 40959999/100.00f;
Double and Float have inherent imprecision that is impossible to avoid (more info on the why here). Using a double you may not have your number rounded in this scenario but not in all. If you work with something that should never be rounded (like prices), you should be using BigDecimal instead.
Implement your int value like shown. Rather than using float use BigDecimal instead.
BigInteger b1 = BigInteger.valueOf(40959999);
int scale = 2;
BigDecimal d1 = new BigDecimal(b1, scale);
System.out.println(d1);
run:
409599.99
Related
I've been trying to sum up decimal values using double in java and it doesn't work well, got a wrong answer.
I've already tried with Double, Float, BigDecimal.
{
double a = 2595.00;
double b = -1760.76;
double c = -834.00;
double d = -.24;
System.out.print(a+b+c+d);
}
The expected result should be "0" But Got 9.1038288019262836314737796783447265625E-15
You can use BigDecimal for this purpose and make sure you input the numbers as String in the BigDecimal constructor:
BigDecimal a = new BigDecimal("2595.00");
BigDecimal b = new BigDecimal("-1760.76");
BigDecimal c = new BigDecimal("-834.00");
BigDecimal d = new BigDecimal("-.24");
System.out.println(a.add(b).add(c).add(d));
Live Example
Output is:
0.00
From the Java docs for BigDecimal(String):
This is generally the preferred way to convert a float or double into
a BigDecimal, as it doesn't suffer from the unpredictability of the
BigDecimal(double) constructor.
Check this SO thread for why double results in a loss of precision.
As already pointed by the previous answers about double precision, the value here is very close to zero. You can see it with System.out.format as well.
System.out.format("%.14f%n",a+b+c+d);
System.out.format("%1.1f%n",a+b+c+d); //to print 0.0
I have below code:
Double a = new Double((123456798/1000000)); //123456798 this value comes from client side as a `int`
DecimalFormat df = new DecimalFormat("###.###");
log.info("a :"+a+" df "+df.format(a.doubleValue()));
output:
a :123.0 df 123
//i want output like this, a :123.xxx fd 123.xxx
please help
UPDATE:
123456798 this value comes from client side as a int so i cant do it as 123456798.0 (or something)
123456798 and 1000000 are int literals, so dividing them will use integer arithmetic, and yield 123.
Instead, you could use floating point literals in order to use floating point arithmetic:
Double a = new Double((123456798.0/1000000.0));
DecimalFormat df = new DecimalFormat("###.###");
log.info("a :"+a+" df "+df.format(a.doubleValue()));
Any one value in the division should be float or double.
Double a = new Double((123456798.0/1000000));
or
Double a = new Double((123456798/1000000.0));
if you are getting these values in variables, then multiply it with 1.0
like
Double a = new Double((variable*1.0/1000000));
Put it like that
Double a = new Double((123456798.0/1000000.0)); // <- note ".0"
the reason of the misbehavior is the integer division:
123456798/1000000
is the integer value, while
123456798.0/1000000.0
is the floating point one (double)
Double a = new Double((123456798/1000000));
You are doing integer division here. Make one of the constants a double, so that floating-point division is done. Also, why are you using Double? It's better to use the primitive type double.
double a = 123456798.0 / 1000000;
Or simply, since they are constants:
double a = 123.456789;
You perform an integer division, thats why a is incorrect:
Double a = new Double(123456798.0/1000000);
I have google on how to get 2 decimal for a float number in java. Below are my codes. Finally here float totalWeight = 0.1*levinWeight+0.8*lsmWeight; I get the error of possible loss of precision ? I would want to first covert the string into float and then have it to be 2 decimal places.
float levinWeight = Float.parseFloat(dataOnlyCombine[2]);
float lsmWeight = Float.parseFloat(dataOnlyCombine[3]);
DecimalFormat df = new DecimalFormat("#.##");
levinWeight = Float.valueOf(df.format(levinWeight));
lsmWeight = Float.valueOf(df.format(lsmWeight));
float totalWeight = 0.1*levinWeight+0.8*lsmWeight;
If you are concerned about precision
don't use float, it has the lowest precision of any option available. I suggest using double or BigDecimal
use operation which involve values which can be accurately represented. 0.1 * x will give you error because 0.1 cannot be represented precisely. Using x / 10.0 will have less error.
I would write something like this
double levinWeight = Double.parseDouble(dataOnlyCombine[2]);
double lsmWeight = Double.parseDouble(dataOnlyCombine[3]);
double totalWeight = (levinWeight + 8 * lsmWeight) / 10.0;
// perform rounding only at the end as appropriate.
// to round to two decimal places
double totalWeight2 = Math.round(totalWeight * 100) / 100.0;
float levinWeight = Float.parseFloat(dataOnlyCombine[2]);
float lsmWeight = Float.parseFloat(dataOnlyCombine[3]);
float totalWeight = 0.1*levinWeight+0.8*lsmWeight;
DecimalFormat df = new DecimalFormat("#.##");
String totalWeightValue = df.format(totalWeight);
If you really want to do it like that, then use BigDecimal. Those floating point classes are perfect for precision. Take a look at them:
http://voidexception.weebly.com/java-bigdecimal---dealing-with-high-precision-calculations.html
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
http://www.javaworld.com/article/2075315/core-java/make-cents-with-bigdecimal.html
Default IEEE 746 floating points will not suit your needs. Alternatively, you could use integers and thread them factor 100. So:
100 is equivalent to 1.00
452 is equivalent to 4.52
1 is equivalent to 0.01
I'm not sure if I'm doing this right.
I'm doing scientific calculations that need to be accurate as possible so I am converting the existing use of Double to BigDecimal.
// before
double tmp = x - (y / z);
// after
BigDecimal tmp = new BigDecimal(
x.value().subtract(y.value().divide(z.value())).toString());
Is this logical or what?
You are doing your arithmetics with doubles before converting the result to BigDecimal. That way you don't gain any precision.
You should convert every number to BigDecimal as soon as possible and then use the methods of BigDecimals (subtract, divide and so on) on the BigDecimal representation to do the arithmetics.
BigDecimal bdX = new BigDecimal(x);
BigDecimal bdY = new BigDecimal(y);
BigDecimal bdZ = new BigDecimal(z);
BigDecimal tmp = bdX.subtract(bdY.divide(bdZ));
BigDecimal has methods for all the operators. You should use them instead. You can also control (specify) the scale and rounding.
Avoid using doulbles, instead use BigDecimal from the beginning.
Assuming that x, y and z are doubles
BigDecimal tmp = new BigDecimal(x).subtract(
new BigDecimal(y).divide(new BigDecimal(z), MathContext.DECIMAL64));
see BigDecimal.divide API to understand why to use MathContext
I need to write a small Java program that deals with calculations involving money. Therefore it needs to have accuracy. (Eg: No float/double variables, only long).
Unfortunately, the original value I need to use is imported through a method which can only read variables as "double".
Now, I tried casting it to a long using a method similar to:
double importedValue = x;
double importedValueConverted = (long) x;
However, when I try dividing importedValueConverted by another "long" variable I get:
required: long
found: double
error: possible loss of precision
Why is that?
double importedValue = x;
double importedValueConverted = (long) x;
Note that both of these variables are declared as 'double'. This results in your error (paraphrasing): (the operation you're doing requires a) long (but when it tried it found a) double.
You want:
double importedValue = x;
long importedValueConverted = (long) x;
Forget all the casting business. If you are working with financial calculations, you can directly use BigDecimal to wrap the doubles returned by your so called method and use an appropriate rounding mechanism provided by BigDecimal that suits your needs.
Update:
This post raised an additional question which I don't think was ever answered-- why use int, or better yet, long or BigDecimal for currency calculations. This is answered here:
Why not to use double or float to represent currency (or where any exact calculations are needed)?
Because floats and doubles cannot accurately represent most base 10
real numbers.
And even when using BigDecimal, one must use the String constructor and not the float one.
This all said, your best bet is to:
Convert all values to cents and store as a long (multiply each dollar amount by 100)
Do the operations in cents
Convert back to dollars by dividing by 100 at the end
This will retain the accuracy desired. Obviously this solution has USD in mind, any conversions to foreign currencies would need appropriate consideration.
Rather than casting, consider rounding to the nearest long value:
double d = 1234.56;
long x = Math.round(d);
Tho really I ask why you'd want to go from a double to a long, as this is going to lose you the precision of the decimal values.
If you want to keep some precision (up to 3 digits, say), and you can absolutely only work with long to do so, you can multiply both doubles by 1,000, then scale all later operations by the same factor, and then scale them all back at the end, like so:
double starting = 1234.5678;
double worker = starting * 1000;
long roundedWorker = Math.round(worker);
// do other computations here...
// due to earlier scaling, adding 1000 is equivalent to adding 1 to the original
long longResult = roundedWorker + 1000;
double threeDigitPreciseResult = longResult / 1000d;
System.out.println("Adding 1 to original number as a long: " + threeDigitPreciseResult);
Update
After getting a better explanation of the problem, it sounds like what you're looking for is the functionality provided by DecimalFormat. Below is a method roundToTwoDecimals() which uses it, along with a test case demonstrating it:
import java.text.DecimalFormat;
import org.junit.Test;
public class ExampleTest {
#Test
public void test() {
double num1 = 29334.32942032432;
double num2 = 438.95940;
double result = num1 / num2;
System.out.println("Before rounding: " + result);
double rounded = roundToTwoDecimals(result);
System.out.println("After rounding: " + rounded);
}
public double roundToTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
}
Which prints out:
Before rounding: 66.82697629968585
After rounding: 66.83
You're casting x to a long than trying to assign it to a double.
That doesn't make sense.
If you want a long, you should use a long.
long longValue = (long) 4.64;
If you wanna cast double to long you do below.
double importedValue = 8.0;
long importedValueConverted = (long) 8.0;
System.out.println(importedValueConverted/(long)8);
OUTPUT: 1
double importedValue = x;
double importedValueConverted = (long) x;
you were trying to cast a double to long and reassign the casted value to a double. you should assign it to long.
Why not look at BigDecimal. It works well when I have used it. Be careful using the Double ctor though as Double is not that precise (eg it cannot accurately store 0.1). It may be more useful to use the String ctor for BigDecimal