23

In another Bruce Eckel exercise, the code I've written takes a method and changes value in another class. Here is my code:

class Big {
  float b;
}

public class PassObject {
  static void f(Letter y) {
    y.c = 'z';
  } //end f()
  static void g(Big z) {
    z.b = 2.2;
  }

  public static void main(String[] args ) {
    Big t = new Big();
    t.b = 5.6;
    System.out.println("1: t.b : " + t.b);
    g(x);
    System.out.println("2: t.b: " + t.b);
  } //end main
}//end class

It's throwing an error saying "Possible loss of precision."

PassObject.java:13: possible loss of precision
found: double
required : float   z.b = 2.2
passobject.java:20: possible loss of precision
found : double
required : float   t.b = 5.6

Can't doubles be floats as well?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
phill
  • 13,434
  • 38
  • 105
  • 141

6 Answers6

33

Yes, but you have to specify that they are floats, otherwise they are treated as doubles:

z.b = 2.2f

The 'f' at the end of the number makes it a float instead of a double.

Java won't automatically narrow a double to a float.

mipadi
  • 398,885
  • 90
  • 523
  • 479
18

No, floats can be automatically upcast to doubles, but doubles can never be floats without explicit casting because doubles have the larger range.

float range is 1.40129846432481707e-45 to 3.40282346638528860e+38

double range is 4.94065645841246544e-324d to 1.79769313486231570e+308d

Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • 9
    'floats can be doubles, but doubles can never be floats'. that's wrong. doubles can be floats if they lay within the float's range. – Fabian Bigler Oct 11 '13 at 06:40
  • What if I wanted to store like `4.1` in a `float`, I can't because it doesn't pass `3.4xxx` range? can't seem to understand why the high bound starts at `3.xxx` when u can obviously store `999.99` no problem. I'm guessing the more decimal points you add the less you can use in front of the decimal point? so why is it `3.XX` shouldn't it be `0.XX` as maximum? – SSpoke Mar 03 '14 at 10:20
  • @SSpoke (I never got notified of this comment so I'm just responding to it now) Those ranges are scientific notation... that's approximately 340,282,346,638,528,860,000,000,000,000,000,000,000.0 in decimal for a float's upper bound. – Powerlord Jun 09 '14 at 13:31
  • @fabigler Only if you explicitly cast it. Otherwise, you'll get a compile error... the very compile error being asked about in the question. – Powerlord Jun 09 '14 at 13:33
  • @Powerlord how can float store such a big number as `40,282,346,638,528,860,000,000,000,000,000,000,000` if it only takes 4 bytes of data? I would assume about 4 billion would be the limit unless floats have some kind of compression? I do understand floats/doubles are lossy and can never store a exact value therefore should never be used for currency values. – SSpoke Jun 09 '14 at 17:36
  • @SSpoke `float` is [Single-precision](http://en.wikipedia.org/wiki/Single-precision_floating-point_format) [IEEE754 floating point number](http://en.wikipedia.org/wiki/IEEE_floating_point). Floating point numbers are stored as a sign bit and a pair of numbers that make up the expression `x * 2^y`. For a `float`, from left to right, the bits are 1 bit for the sign, 8 bits for the exponent, and 23 bits for the base number (or *mantissa*). – Powerlord Jun 10 '14 at 13:36
9

By default, Java will treat a decimal (e.g. "4.3") as a double unless you otherwise specify a float by adding an f after the number (e.g. "4.3f").

You're having the same problem on both lines. First, the decimal literal is interpreted as a double by the compiler. It then attempts to assign it to b, which is of type float. Since a double is 64 bits and a float is only 32 bits (see Java's primitives documentation), Java gives you an error indicating that the float cannot fit inside the double. The solution is to add an f to your decimal literals.

If you were trying to do the opposite (i.e. assign a float to a double), that would be okay since you can fit a float's 32 bits within a double's 64.

mtlynch
  • 3,403
  • 4
  • 31
  • 31
6

Don't use float. There is almost never a good reason to use it and hasn't been for more than a decade. Just use double.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    I guess you've never done any OpenGL related development via Java... :P – User Apr 25 '17 at 03:40
  • 1
    @Manius I have done in the last 8 years since I wrote this however more powerful GPU mean there isn't much difference between using float or double for the use cases that I have worked on. The main problem has been feeding the data to the GPU fast enough. – Peter Lawrey Apr 25 '17 at 15:49
  • 1
    Agreed. Just picking on ya a little (yeah, that's an OLD answer I see now). :) It really would be nice if we could just dump floats entirely by now, but... – User Apr 25 '17 at 19:23
  • 1
    @Manius if anything I would like to see 128-bit floating point support in hardware etc. – Peter Lawrey Apr 26 '17 at 08:00
  • 1
    Hah, no argument here! – User Apr 28 '17 at 05:01
  • 1
    @Manius something like C#'s decimal which uses 128-bits. – Peter Lawrey Apr 29 '17 at 07:30
3
can't doubles be floats as well?

No. Each value or variable has exactly one type (double, float, int, long, etc...). The Java Language Specification states exactly what happens when you try to assign a value of one type to a variable of another type. Generally, assignments of a "smaller" value to a "larger" type are allowed and done implicitly, but assignments where information could be lost because the target type is too "small" to hold all values of the origin type are not allowed by the compiler, even if the concrete value does fit into the target type.

That's why the compiler complains that assigning a double value (which the literal implicitly is) to a float variable could lose information, and you have to placate it by either making the value a float, or by casting explicitly.

One area that often causes confusions is calculations, because these are implicitly "widened" to int for technical reasons. So if you multiply two shorts and try to assign the result to a short, the compiler will complain because the result of the calculation is an int.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
0

float range is lower than double so a float can be easily represented in double, but the reverse is not possible because, let say we take a value which is out of float range then during convention we will lose the exact data

sumanta
  • 359
  • 3
  • 7