I have a very simple piece of code below which I think gives the wrong result from a user's perspective.
package com.test.sample;
public class Test {
public static void main(String[] args) {
float c,d;
c = (float) 12.47;
d = (float) 12.44;
d = c - d;
System.out.println("Hello the calculated value of a=" + d);
}
}
The output is
Hello the calculated value of a=0.030000687
But I want a=0.030000000 which is the perfect value.
Floating point arithmetic, what developers should know.
The JVM implements the IEEE-754 1985 floating point standard and it has its accuracy problem (since floating point numbers cannot precisely represent all real numbers).
If you seek accuracy, use java.math.BigDecimal object instead.
Update: This is how I took your example and used BigDecimal to achieve your expected result:
import java.math.BigDecimal;
/**
* #author The Elite Gentleman
*
*/
public class BigDecimalTest {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
BigDecimal a = new BigDecimal(Float.toString(12.47f));
BigDecimal b = new BigDecimal(Float.toString(12.44f));
BigDecimal c = a.subtract(b);
System.out.println(c);
}
}
Related
i have this code, variables first, second and third only can obtain in double i need format in percent to write later on other place
import java.text.DecimalFormat;
public class Main {
public static void main(String[] argv) throws Exception {
double first = 0.5;
double second = 1.5;
double third = 2.5;
DecimalFormat df = new DecimalFormat("#%");
System.out.println(df.format(first));
System.out.println(df.format(second));
System.out.println(df.format(third));
}
}
output:
50%
150%
250%
i need obtain this result
-50%
50%
150%
i hope any can help me with this thanks
I looks like you need values relative to 100%, so you just need to subtract 1 (i.e. 100%) from your values:
System.out.println(df.format(first - 1));
System.out.println(df.format(second - 1));
System.out.println(df.format(third - 1));
I have encountered something strange today. The below code compiles unexpectedly and runs fine.
public class Test {
public static void func(double d) {
System.out.print("d : " + d);
}
public static void main(String[] args) {
float f = 10.0f;
func(f); // output: d : 10.0
}
}
But this one gives compilation error
public class Test {
public static void func(float f) {
System.out.print("f : " + f);
}
public static void main(String[] args) {
double d = 10.0d;
func(d);
}
}
Can somebody please explain this behaviour ?
Type promotion from float to double is safe as no data is lost and all float 4 bytes can fit into double 8 byes.
However the opposite, from double to float, always truncates the data as double 8 bytes can't fit into float 4 bytes. Compiler guards against doing this truncation accidentally by forcing the programmer to manually specify the type conversion.
double(8 byte) is a bigger data type than float(4 byte) so you can store float(4 byte) in double(8 byte) but you can't double in float. If you try to do that you'll get Possible loss of precision error.
So the following will give error.
float f = 120.55;
While this one don't
double d = 120.44f;
I'm using the following method on Windows 8 (Intel Atom Z3775):
public static strictfp void main(String args[])
{
float a = 0.000000002f;
float b = 90000300000000004f;
float c = a * b;
System.out.println(c);
}
which gives me: 1.80000592E8
When running
public strictfp void calculate()
{
float a = 0.000000002f;
float b = 90000300000000004f;
float c = a * b;
Toast.makeText(getApplicationContext(), c + "", Toast.LENGTH_LONG).show();
}
i get: 1.8000059E8
Why do they differ? Am I using strictfp wrong?
You have confirmed that printing the hex representation of the floats shows that the values are the same:
String.format("%08x", Float.floatToIntBits(c))
This means that there is a difference in the implementation of how a float is converted to a String.
Notice that the OpenJDK implementation of java.lang.Float.toString(float) invokes a method from sun.misc.FloatingDecimal - i.e. it is a JDK-specific implementation.
You'd need either:
To ensure that you always run the code using the same implementation
To provide your own implementation which always produces the same result
To specify a shorter format, so that the strings are the same to that many decimal places.
Well, the displaying method certainly differs...
I was doing some arithmetic program today and I got a real funny result passing the result of float division to a setter :
class A {
Float f;
setF(Float f) {
this.f=f;
print (f)
}
}
Long x=7L;
Long y=3L;
print (x/y.floatValue() )
a.setF(x/y.floatValue());
the result of the above pseudo program is something like this in the jdk 1.6
2.333333
2.0
any clue on where the round is performed?
Let me explain your first condition i.e. `x/y.floatValue()' what you are doing is:
long/ float because you are taking float value from variable y from floatValue() method so according to its implementation, you will get y = 3.0F.
/**
* Returns the value of this {#code Long} as a
* {#code float}.
*/
public float floatValue() {
return (float)value;
}
Your division will be 7L/ 3F or say 7/ 3.0 which will give you the result as 2.333333
Your second condition a.setF(x/y.floatValue()); will also result 2.333333 check if you missed something or post your whole code.
As you can see in console header I am using JDK1.6
It's a casting issue. Your x is still type long, whereas y.floatValue() is a float.
Both the divisor and the dividend need to be float or double to get what you want, so try for example, this:
Long x=7L;
Long y=3L;
System.out.println((float) x/(float) y);
result -> 2.3333333
This rounding down to 2.0 does not happen, there may be a problem with how you wrote the code from that pseudo-code
I tested with this implementation
public class A {
Float f;
void setF(Float f){
this.f=f;
System.out.println(f);
}
public static void main(String[] args) {
Long x=7L;
Long y=3L;
System.out.println(x/y.floatValue());
new A().setF(x/y.floatValue());
}
}
This is the result
2.3333333
2.3333333
This is one of my classes that I am testing. It keeps failing the calculateVolume() method and I am not sure why.
package shape3D;
public class Sphere implements Cloneable {
private double myRadius;
private double myVolume;
private double mySurfaceArea;
private final static double pi = 3.14;
public static void main(String args[]){
Sphere sphere = new Sphere();
}
public double calculateVolume(){
myVolume = (4/3)*pi*(Math.pow(myRadius,3));
return myVolume;
}
public double calculateSurfaceArea(){
mySurfaceArea = ((4)*(pi)*(Math.pow(myRadius,2)));
return mySurfaceArea;
}
public double getSurfaceArea(){
return this.calculateSurfaceArea();
}
public double getVolume(){
return this.calculateVolume();
}
public void setRadius(double radius2){
myRadius = radius2;
}
public String toString(){
return "Volume: " + this.getVolume() + " Surface area " + this.getSurfaceArea();
}
public Sphere clone (){
Sphere p = new Sphere();
p.setRadius(myRadius);
return p;
}
}
Here is the JUnit test case I am using
public class sphereTest {
#Test
public void testSphere(){
shape3D.Sphere sphere = new shape3D.Sphere();
sphere.setRadius(6);
assertTrue(sphere.calculateSurfaceArea()== 452.16);
assertTrue(sphere.calculateVolume()== 904.32);
The calculateSurfaceArea() stuff passes fine but the volume is failing and I am not sure why.
The calculation
myVolume = (4/3)*pi*(Math.pow(myRadius,3));
Uses integer arithmetic: 4/3 evaluates to 1.
Change it to
myVolume = (4.0/3)*pi*(Math.pow(myRadius,3));
You're doing integer division when calculating the volume truncating the first term of the equation to 1. Replace
myVolume = (4 / 3) * pi * (Math.pow(myRadius, 3)); // 678.24
with
myVolume = (4 / 3.0) * pi * (Math.pow(myRadius, 3)); // 904.31
Due to floating point imprecision you will still need to allow for the difference between the expected & calculated values. You can use this version of assertEquals which allows a delta value to do the comparison - replace
assertTrue(sphere.calculateVolume()== 904.32);
with
assertEquals(sphere.calculateVolume(), 904.32, .02);
Quite aside from the 4/3 integer problem (which I failed to spot): It's not safe to compare two Java double values this way.
If you use assertEquals instead of assertTrue then you might see the problem. I'm betting that it's calculating 4/3 first, then truncating it. And it'll still do this even if you make those into doubles.
Use the overload for assertEquals as mentioned in this question.