简体   繁体   中英

int or float to represent numbers that can be only integer or “#.5”

Situation

I am in a situation where I will have a lot of numbers around about 0 - 15. The vast majority are whole numbers, but very few will have decimal values. All of the ones with decimal value will be "#.5", so 1.5, 2.5, 3.5, etc. but never 1.1, 3.67, etc.

I'm torn between using float and int (with the value multiplied by 2 so the decimal is gone) to store these numbers.

Question

Because every value will be .5, can I safely use float without worrying about the wierdness that comes along with floating point numbers ? Or do I need to use int ? If I do use int , can every smallish number be divided by 2 to safely give the absolute correct float ?

Is there a better way I am missing?

Other info

I'm not considering double because I don't need that kind of precision or range.

I'm storing these in a wrapper class, if I go with int whenever I need to get the value I am going to be returning the int cast as a float divided by 2.

What I went with in the end

float seems to be the way to go.

This is not a theoretical proof but you can test it empirically:

public static void main(String[] args) {
  BigDecimal half = new BigDecimal("0.5");
  for (int i = 0; i < Integer.MAX_VALUE; i++) {
    float f = i + 0.5f;
    if (new BigDecimal(f).compareTo(new BigDecimal(i).add(half)) != 0) {
      System.out.println(new BigDecimal(i).add(half) + " => " + new BigDecimal(f));
      break;
    }
  }
}

prints:

8388608.5 => 8388608

Meaning that all xxx.5 can be exactly represented as a float between 0.5 and 8388607.5.

For larger numbers float's precision is not enough to represent the number and it is rounded to something else.

Let's refer to the subset of floating point numbers which have a decimal portion of .0 or .5 as point-five floats, or PFFs.

The following properties are guaranteed:

  • Any number up to 8 million or so (2^23, to be exact) which ends in .0 or .5 is representable as a PFF.
  • Adding/subtracting two PFFs results in a PFF, unless there's overflow.
  • Multiplying a PFF by an integer results in a PFF, unless there's overflow.

These properties are guaranteed by the IEEE-754 rules, which give a 24-bit mantissa and guarantee exact rounding of exact results.

Using int s will give you a somewhat larger range.

There will be no accuracy issues with .5's with float for that range, so both approaches will work.

If these represent actual number values, I would chose the float simply because it consumes the same amount of memory and I don't need to write code to convert between some internal int representation and the exposed float value.

If these numbers represent something other than a value, eg a grade from a very limited set, I would consider modelling them as an enum, depending on how these are ultimately used.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM