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 等
我在使用 float
和 int
(值乘以 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 位尾数并保证精确结果的精确舍入。
使用 int
s 会给你一个更大的范围。
对于该范围,带浮点数的 .5 不会有精度问题,因此这两种方法都有效。
如果这些代表实际数值,我会选择 float,因为它消耗相同数量的内存,而且我不需要编写代码来在某些内部 int 表示和公开的 float 值之间进行转换。
如果这些数字代表的不是一个值,例如来自非常有限的一组的成绩,我会考虑将它们建模为枚举,具体取决于它们的最终使用方式。
情况
我的处境是我会有很多大约 0 - 15 的数字。绝大多数是整数,但很少有小数。所有具有十进制值的都将是“#.5”,因此 1.5、2.5、3.5 等,但绝不会是 1.1、3.67 等
我在使用 float
和 int
(值乘以 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 位尾数并保证精确结果的精确舍入。
使用 int
s 会给你一个更大的范围。
对于该范围,带浮点数的 .5 不会有精度问题,因此这两种方法都有效。
如果这些代表实际数值,我会选择 float,因为它消耗相同数量的内存,而且我不需要编写代码来在某些内部 int 表示和公开的 float 值之间进行转换。
如果这些数字代表的不是一个值,例如来自非常有限的一组的成绩,我会考虑将它们建模为枚举,具体取决于它们的最终使用方式。