十进制值问题
Decimal value issue
我有一个非常烦人的任务要做,并且坚持了下来。
所以:我需要编写一个函数来返回小数点后的浮点数的值。
例如:参数为 be:5.456-> 返回值为 be:456.
我不能使用字符串(当然这样会很容易)。
你有什么建议吗?
需要一些步骤才能使用 float
或 double
等原语。如果允许您使用 BigDecimal
,这只是一行代码。
给定 double d = 5.456
;
- 首先,把浮点数前面的部分剪掉。
- 按
int full = (int)d;
执行此操作,这将是 5
- 从中减去全部:
d-full
现在只是点之后的部分,所以 .456
- 现在使用循环将值乘以 10,直到“点后”部分为 0。
这里的特殊之处在于,当您使用 double 时,您会遇到浮点精度问题。这意味着 d
将具有介于两者之间的值 0.4560000000000004
。为了解决这个问题,让我们引入一个 epsilon。
完整代码如下所示:
private static final double EPS = 1e-5;
public static void main(String[] args) {
double d = 5.456;
System.out.println(afterDot(d));
}
private static int afterDot(double d) {
d = getDecimals(d);
while(getDecimals(d) > EPS){ //decimals will likely never be 0 because of precision, so compare with a really small EPS instead of 0
d *= 10;
}
//cast the result to an int to cut off the double precision issues
return (int)d;
}
private static double getDecimals(double d) {
int full = (int) d;
d = d-full;
return d;
}
这会打印 456
。我非常确定这可以以某种方式进行优化,但这是一个有效的初稿。
你想要的是余数,乘以 10 直到余数为 0。使用 BigDecimal
来防止看起来像这样的舍入问题:
final BigDecimal input = new BigDecimal("5.456");
BigDecimal x = input.remainder(BigDecimal.ONE);
while (x.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) > 0) {
x = x.multiply(new BigDecimal(10));
}
System.out.println(x.longValue());
这里有两种不针对浮点异常进行调整的方法。
double s = 5.456;
System.out.println(s%1);
或
System.out.println(s-(int)s);
同时打印
0.4560000000000004
或使用BigDecimal
并调整比例并减去整数值。
System.out.println(BigDecimal.valueOf(s)
.setScale(3)
.subtract(BigDecimal.valueOf((int)s)));
打印
.456
我有一个非常烦人的任务要做,并且坚持了下来。 所以:我需要编写一个函数来返回小数点后的浮点数的值。 例如:参数为 be:5.456-> 返回值为 be:456.
我不能使用字符串(当然这样会很容易)。
你有什么建议吗?
需要一些步骤才能使用 float
或 double
等原语。如果允许您使用 BigDecimal
,这只是一行代码。
给定 double d = 5.456
;
- 首先,把浮点数前面的部分剪掉。
- 按
int full = (int)d;
执行此操作,这将是 5 - 从中减去全部:
d-full
现在只是点之后的部分,所以.456
- 按
- 现在使用循环将值乘以 10,直到“点后”部分为 0。
这里的特殊之处在于,当您使用 double 时,您会遇到浮点精度问题。这意味着 d
将具有介于两者之间的值 0.4560000000000004
。为了解决这个问题,让我们引入一个 epsilon。
完整代码如下所示:
private static final double EPS = 1e-5;
public static void main(String[] args) {
double d = 5.456;
System.out.println(afterDot(d));
}
private static int afterDot(double d) {
d = getDecimals(d);
while(getDecimals(d) > EPS){ //decimals will likely never be 0 because of precision, so compare with a really small EPS instead of 0
d *= 10;
}
//cast the result to an int to cut off the double precision issues
return (int)d;
}
private static double getDecimals(double d) {
int full = (int) d;
d = d-full;
return d;
}
这会打印 456
。我非常确定这可以以某种方式进行优化,但这是一个有效的初稿。
你想要的是余数,乘以 10 直到余数为 0。使用 BigDecimal
来防止看起来像这样的舍入问题:
final BigDecimal input = new BigDecimal("5.456");
BigDecimal x = input.remainder(BigDecimal.ONE);
while (x.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) > 0) {
x = x.multiply(new BigDecimal(10));
}
System.out.println(x.longValue());
这里有两种不针对浮点异常进行调整的方法。
double s = 5.456;
System.out.println(s%1);
或
System.out.println(s-(int)s);
同时打印
0.4560000000000004
或使用BigDecimal
并调整比例并减去整数值。
System.out.println(BigDecimal.valueOf(s)
.setScale(3)
.subtract(BigDecimal.valueOf((int)s)));
打印
.456