Java 如何提取double/BigDecimal的小数位数

Java 如何提取double/BigDecimal的小数位数,java,Java,假设我们有一个双倍值12345.6789(应该是动态的) 现在要求将数字拆分,得到小数位数和小数位数,即: double number = 12345.6789; int decimal = 12345; int fractional = 6789; 我算出了小数部分,但你能给我一个小数部分的提示吗?非常感谢。你不能用精确的方式做你想做的事 一个问题是,如果您有数字1.05,结果应该是什么 double number = 1.05; int decimal = 1; int fractiona

假设我们有一个双倍值
12345.6789
(应该是动态的)

现在要求将数字拆分,得到小数位数和小数位数,即:

double number = 12345.6789;
int decimal = 12345;
int fractional = 6789;

我算出了小数部分,但你能给我一个小数部分的提示吗?非常感谢。

你不能用精确的方式做你想做的事

一个问题是,如果您有数字
1.05
,结果应该是什么

double number = 1.05;
int decimal = 1;
int fractional = 5; // Oops! "1.05" and "1.5" give the same result.
这个怎么样

int fractional = 05; // Still not correct. This is an octal number.
另一个问题是双精度类型不能准确表示
12345.6789
。它存储的数字略有不同。这称为表示错误。所以分数部分实际上不是
6789
。相反,您可以将其四舍五入到小数位数

int fractional = (int)Math.round((number - decimal) * 1000);

您可以转换为
字符串
,找到小数点,获取子字符串,然后再转换回整数

String numberStr = Double.toString(number);
String fractionalStr = numberStr.substring(numberStr.indexOf('.')+1);
int fractional = Integer.valueOf(fractionalStr); 
这里的问题是,小数部分不是作为“0.6789”写入内存,而是可能有某些“偏移”,也就是说。例如,
0.6789
可以存储为
0.67889999291293929991

我认为您主要关心的不是获取分数部分,而是以一定的精度获取分数部分

如果你想得到你分配给它的确切值,你可能想考虑这个问题(Altho,它不是一个干净的解决方案):


但是,正如我所说,这不是最有效、最干净的解决方案。

您必须决定支持多少小数。我使用这种方法:

int decimals = 2;
BigDecimal value = new BigDecimal(123.45).setScale(decimals, RoundingMode.HALF_EVEN);
BigInteger INTEGER = value.abs().toBigInteger();
//(value - INTEGER) * (10 ^ decimais)
BigInteger DECIMAL = ((value.subtract(new BigDecimal(INTEGER))).multiply(new BigDecimal(10).pow(decimals))).toBigInteger();

不会一直有效,因为分数部分可以有超过4位数:)@Mark Byers谢谢你的解决方案,但是分数部分是动态的,所以我们不知道需要多长时间,*1000解决方案可能无法工作。如果double是12345.678,那么它就变成了*100。@子规则:我没有给你一个解决方案,我给了你一个解释,解释了为什么在不改变要求的情况下不能实现它。您愿意更改哪项要求?@Mark Byers可能会转换为字符串和进程,返回可能是一个解决方案?您需要决定是否要查找打印表示的小数部分,或者,如果您愿意接受实际二进制表示中的精度差异。@seh有一个区别,即小数应该只包含没有穿孔的数字。唯一的方法是设置要使用的小数数。。。有两个小数的示例:0.01表示1,0.10表示10。请看我的答案。这不是一个完全重复的数字,因为这里要求分数位数为int。它需要一个用于split方法的正则表达式字符串参数。因此,您需要使用“\\.”ref:对于“精确值”的第二个解决方案,如果分数部分以0开头,您将丢失这些0,并以一个非常不同的数字结束。适用于
double
,但不适用于
double
。当double.toString返回科学指数表示法时不起作用。
String doubleAsText = "12345.6789";
double number = Double.parseDouble(doubleAsText);
int decimal = Integer.parseInt(doubleAsText.split("\.")[0]);
int fractional = Integer.parseInt(doubleAsText.split("\.")[1]);
int decimals = 2;
BigDecimal value = new BigDecimal(123.45).setScale(decimals, RoundingMode.HALF_EVEN);
BigInteger INTEGER = value.abs().toBigInteger();
//(value - INTEGER) * (10 ^ decimais)
BigInteger DECIMAL = ((value.subtract(new BigDecimal(INTEGER))).multiply(new BigDecimal(10).pow(decimals))).toBigInteger();