Java 如何将双精度长度四舍五入到n(不是小数点后n位)?
我一直试图找到一种方法来确保双“值”的长度不大于10。然而,由于我没有将其四舍五入到小数点后的某个数字,因此编程变得越来越困难 例如,1234567.8912和12.345678912都大于10位,但它们必须四舍五入到不同的小数位数。我的逻辑是找到小数点的位置,并将双精度四舍五入到“小数点前的10位数” 我创建了两种不同的方法,但两种方法似乎都不能正常工作Java 如何将双精度长度四舍五入到n(不是小数点后n位)?,java,double,rounding,Java,Double,Rounding,我一直试图找到一种方法来确保双“值”的长度不大于10。然而,由于我没有将其四舍五入到小数点后的某个数字,因此编程变得越来越困难 例如,1234567.8912和12.345678912都大于10位,但它们必须四舍五入到不同的小数位数。我的逻辑是找到小数点的位置,并将双精度四舍五入到“小数点前的10位数” 我创建了两种不同的方法,但两种方法似乎都不能正常工作 if ((Double.toString(value)).length()> 10){ int counter
if ((Double.toString(value)).length()> 10){
int counter = 0;
double no_of_dec = 1;
double no_of_int = 1;
double new_value = 0;
for (int i = 0; i< (Double.toString(value)).length(); i++){
if ( (Character.toString((Double.toString(value)).charAt(i))).equals(".") ){
counter = 1;
} if (counter == 1){
no_of_dec = no_of_dec * 10;
} else if (counter == 0){
no_of_int = no_of_int * 10;
}
}
no_of_dec = no_of_dec / (no_of_int);
new_value = (double)Math.round(value * 100d/100d);
return Double.toString(new_value);
} else {
return Double.toString(value);
}
if ((Double.toString(value)).length()> 10){
double no_of_dec = 0;
double no_of_int = 0;
double new_value = 0;
for (int i = 0; i< (Double.toString(value)).length(); i++){
while (!(Character.toString((Double.toString(value)).charAt(i))).equals(".")){
no_of_int = no_of_int + 1;
}
}
no_of_dec = (Double.toString(value)).length() - no_of_int;
no_of_dec = no_of_dec * 10;
new_value = (double)Math.round(value * no_of_dec/no_of_dec);
return Double.toString(new_value);
} else {
return Double.toString(value);
}
}
if((Double.toString(value)).length()>10){
int计数器=0;
双no_的_dec=1;
_int=1的双no_;
双新_值=0;
对于(int i=0;i<(Double.toString(value)).length();i++){
if((Character.toString((Double.toString(value)).charAt(i))等于(“.”){
计数器=1;
}如果(计数器==1){
12月的数量=12月的数量*10;
}else if(计数器==0){
非整数=非整数*10;
}
}
无dec=无dec/(无int);
新的_值=(双)数学舍入(值*100d/100d);
返回Double.toString(新的_值);
}否则{
返回Double.toString(值);
}
if((Double.toString(value)).length()>10){
双no_的_dec=0;
双no_的_int=0;
双新_值=0;
对于(int i=0;i<(Double.toString(value)).length();i++){
而(!(Character.toString((Double.toString(value)).charAt(i))等于(“.”){
不含整数=不含整数+1;
}
}
no_of_dec=(Double.toString(value)).length()-no_of_int;
12月的数量=12月的数量*10;
新值=(双精度)数学四舍五入(值*数字编号/数字编号);
返回Double.toString(新的_值);
}否则{
返回Double.toString(值);
}
}
我是这样做的:
private static BigDecimal getRounded(double n, int totalDigits) {
String nString = Double.toString(n); // transform to string to make the job easier
if(nString.contains(".")) {
int dotPos = nString.indexOf("."); // = number of digits before the decimal point
int remainingDigits = totalDigits - dotPos; // = remaining digits after the decimal point
return new BigDecimal(nString).setScale(remainingDigits, BigDecimal.ROUND_HALF_UP); // round
}
return new BigDecimal(n);
}
这是我的测试:
double n = 1234567.8912;
System.out.println(getRounded(n, 10));
n = 12.345678915;
System.out.println(getRounded(n, 10));
结果如下:
1234567.891
12.34567892
演示:具有执行此操作的操作:
double truncate(double value) {
BigDecimal b = new BigDecimal(String.valueOf(value));
b = b.round(new MathContext(10));
return b.doubleValue();
}
使用BigDecimal(String)构造函数而不是BigDecimal(double)构造函数是有原因的。double和float不是以10为基数的数字,因此它们并不完全代表我们在打印它们时看到的值;这本书很好地说明了这一点。这不是Java独有的,在大多数语言中也是如此
更新:
4CARS指出,对于不小于1的非零个数,这将不起作用,因为BigDePiple不认为零整数部分是一个有效的数字。你可以解决这个问题:
double truncate(double value) {
int precision = 10;
if (value != 0 && Math.abs(value) < 1) {
precision--;
}
BigDecimal b = new BigDecimal(String.valueOf(value));
b = b.round(new MathContext(precision));
return b.doubleValue();
}
双截断(双值){
整数精度=10;
如果(值!=0&&Math.abs(值)<1){
精度--;
}
BigDecimal b=新的BigDecimal(String.valueOf(value));
b=b.round(新的MathContext(精度));
返回b.doubleValue();
}
更新2:
反斜杠指出,对于-1和1之间的非零数,它比上面的更复杂。我确信可以计算出所需的精确精度,但我认为更简单的方法是,为了四舍五入的目的,只需添加1即可消除该问题:
double truncate(double value) {
BigDecimal b = new BigDecimal(String.valueOf(value));
MathContext context = new MathContext(10);
if (value > 0 && value < 1) {
b = b.add(BigDecimal.ONE);
b = b.round(context);
b = b.subtract(BigDecimal.ONE);
} else if (value < 0 && value > -1) {
b = b.subtract(BigDecimal.ONE);
b = b.round(context);
b = b.add(BigDecimal.ONE);
} else {
b = b.round(context);
}
return b.doubleValue();
}
双截断(双值){
BigDecimal b=新的BigDecimal(String.valueOf(value));
MathContext=新的MathContext(10);
如果(值>0&&值<1){
b=b.add(BigDecimal.ONE);
b=b.圆形(上下文);
b=b.减法(大十进制1);
}else if(值<0&&value>-1){
b=b.减法(大十进制1);
b=b.圆形(上下文);
b=b.add(BigDecimal.ONE);
}否则{
b=b.圆形(上下文);
}
返回b.doubleValue();
}
如果数字为0.1234567891
前导零是否算作数字?什么是“必须四舍五入到不同的小数位数”?但是,您能举一个例子作为输入和预期输出吗?@4castle yes itdoes@snr例如,1.3456789556和13456.789556都大于10位。但是,它们都有不同的小数位数。因此,对于第一个示例,您必须将其四舍五入到小数点后9位,而对于第二个示例,您必须将其四舍五入到小数点后5位,以使其长度为10位。double没有小数。它们有二进制数字,两个是不可通约的。你所要求的原则上是不可能的。如果您想要十进制数字,请使用十进制基数,例如BigDecimal
。这绝对是最好的解决方案,但我发现前导零(见我上面的注释)不算作精度的一部分,因此,在这种情况下,它给出的数字太多了。将其变回双精度
会破坏BigDecimal
所做的一切。而且BigDecimal
确实有一个来自double
的构造函数。事实上,它不仅仅返回一个数字小于1的多个数字。它每前导零多返回一个数字。例如,我用0.00034567089445515
尝试了这个方法:它返回14位长的0.0003456708945
:10+4个前导零。如果输入try with0.00000000 34567089445515
,则返回0.00000000 3456708945
,长度为19位:10+9个前导零@EJPI解释了为什么应该避免使用BigDecimal(double)构造函数;javadoc很好地解释了这一点。你能举一个输入值被转换破坏的例子吗?我尝试的每个输入值都有效。@反斜杠正确。更新。