int 或 float 表示只能是整数或“#.5”的数字

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

情况

我的处境是我会有很多大约 0 - 15 的数字。绝大多数是整数,但很少有小数。所有具有十进制值的都将是“#.5”,因此 1.5、2.5、3.5 等,但绝不会是 1.1、3.67 等

我在使用 floatint(值乘以 2 所以小数点消失)来存储这些数字之间犹豫不决。

问题

因为每个值 都会 为 .5,我可以安全地使用 float 而不必担心 the wierdness that comes along with floating point numbers 吗?或者我需要使用 int 吗?如果我确实使用 int,是否可以将每个较小的数字除以 2 以安全地给出绝对正确的 float

有没有更好的方法我想念?

其他信息

我不考虑 double 因为我不需要那种精度或范围。

我将这些存储在包装器 class 中,如果我在需要获取值时使用 int,我将返回 int 转换为float 除以 2。

What I went with in the end

float seems to be the way to go.

这不是理论证明,但您可以根据经验进行测试:

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;
    }
  }
}

打印:

8388608.5 => 8388608

意味着所有xxx.5都可以精确表示为0.5到8388607.5之间的浮点数。

对于较大的数字,浮点数的精度不足以表示数字,它会四舍五入为其他数字。

我们将小数部分为 .0 或 .5 的浮点数子集称为五点浮点数或 PFF。

保证以下属性:

  • 任何以 .0 或 .5 结尾的最多 800 万左右(确切地说是 2^23)的数字都可以表示为 PFF。
  • Adding/subtracting 两个 PFF 产生一个 PFF,除非有溢出。
  • PFF 乘以一个整数得到 PFF,除非有溢出。

这些属性由 IEEE-754 规则保证,该规则提供 24 位尾数并保证精确结果的精确舍入。

使用 ints 会给你一个更大的范围。

对于该范围,带浮点数的 .5 不会有精度问题,因此这两种方法都有效。

如果这些代表实际数值,我会选择 float,因为它消耗相同数量的内存,而且我不需要编写代码来在某些内部 int 表示和公开的 float 值之间进行转换。

如果这些数字代表的不是一个值,例如来自非常有限的一组的成绩,我会考虑将它们建模为枚举,具体取决于它们的最终使用方式。