如何在Java中增加固定有效位?
我不确定Java是否有相应的工具,但如果有一个Java解决方案,那就太棒了。 例如,我需要增加Double/Decimal/BigDecimal或类似变量中的第五个有效数字如何在Java中增加固定有效位?,java,double,digit,significant-digits,Java,Double,Digit,Significant Digits,我不确定Java是否有相应的工具,但如果有一个Java解决方案,那就太棒了。 例如,我需要增加Double/Decimal/BigDecimal或类似变量中的第五个有效数字 // Left is what I have. Right is what I need to get 12345 -> 12346 1234567 -> 1234667 123 -> 123.01 0.12345 -> 0.12346 0.1 -> 0.10001 0.0012345 ->
// Left is what I have. Right is what I need to get
12345 -> 12346
1234567 -> 1234667
123 -> 123.01
0.12345 -> 0.12346
0.1 -> 0.10001
0.0012345 -> 0.0012346
123.5 -> 123.51
12.5 -> 12.501
0.000123456789 -> 0.000123466789
对于固定有效数字的递增/递减,是否有任何解决方案
编辑:不准确的算术是可以的。也就是说,如果我们将12.5转为12.50100000000041,就可以了。
最小输入值为0.00001。最大输入值为100000.0。
递增/递减的最大有效位为5。
即增量后最小输出值为0.000010001
从最高有效位到最低有效位的长度不超过10 请注意,在发布答案之前,请至少使用此问题中列出的所有示例编号测试您的解决方案。
我将检查所有答案,以找到最有效的解决方案。最快的方法将被标记为正确的方法。希望这能帮助您:
int position;
BigDecimal[] numbers = {new BigDecimal("12345.0"), new BigDecimal("1234567.0"),
new BigDecimal("0.12345"), new BigDecimal("0.1"),
new BigDecimal("0.0012345"), new BigDecimal("123.5"), new BigDecimal("12.5"),
new BigDecimal("1234500000.0000000012345")};
for (BigDecimal number : numbers) {
System.out.println(number);
String leftPart = String.valueOf(number).replaceAll("^(\\d+)\\.\\d+", "$1");
String rightPart = String.valueOf(number).replaceAll("^\\d+\\.(\\d+)", "$1");
int left = leftPart.length();
int right = rightPart.length();
if (Integer.parseInt(leftPart) == 0) {
position = 6 + rightPart.replaceAll("^([0]*).*", "$1").length();
} else {
position = 5;
}
if (left <= position) {
number = number.add(new BigDecimal(Math.pow(0.1, position - left)));
} else {
number = number.add(new BigDecimal(Math.pow(10, left - position)));
}
System.out.println(number.setScale(right > 5 ? right : 5, RoundingMode.DOWN) + "\n..................................");
}
我可以提出一种有效的方法:
1->1152->3123.65899->8
size>5或5,然后从您的号码中删除“逗号”,并以10**大小的格式保存“逗号”后的号码大小,例如:12345.67=1234567 x 10**-2,0.1234567=1234567 x 10**-7
12345.67=(1234567+1)x10**-2=12345.68,0.99999=(99999+1)x10**-5=1.00000
注意:您可以将此解决方案应用于5之后的任何其他数字。这是我到目前为止的解决方案。这不是很好,因为我需要使用字符串,但它非常快。至少我不知道如何让它更快
public static final DecimalFormat DF = (DecimalFormat) NumberFormat.getNumberInstance(Locale.ENGLISH);
static {
DF.setMaximumFractionDigits(16);
DF.setGroupingUsed(false);
}
public static double fixedSignificantDigitIncrement(double input, int significantDigit){
return input+fixedSignificantDigitAmount(input, significantDigit);
}
public static double fixedSignificantDigitDecrement(double input, int significantDigit){
return input-fixedSignificantDigitAmount(input, significantDigit);
}
public static double fixedSignificantDigitAmount(double input, int significantDigit){
String inputStr = DF.format(input);
int pointIndex = inputStr.indexOf('.');
int digitsBeforePoint;
if(pointIndex==-1){
pointIndex=inputStr.length();
digitsBeforePoint=inputStr.length();
} else {
digitsBeforePoint = pointIndex;
if(digitsBeforePoint==1 && inputStr.charAt(0)=='0') digitsBeforePoint=0;
}
if(significantDigit<=digitsBeforePoint){
return Math.pow(10, digitsBeforePoint-significantDigit);
} else if(digitsBeforePoint==0){
++pointIndex;
for(;pointIndex<inputStr.length();pointIndex++){
if(inputStr.charAt(pointIndex)!='0') break;
}
return 1/Math.pow(10, significantDigit+(pointIndex-2));
}
return 1/Math.pow(10, significantDigit-digitsBeforePoint);
}
public静态final DecimalFormat DF=(DecimalFormat)NumberFormat.getNumberInstance(Locale.ENGLISH);
静止的{
DF.setMaximumFractionDigits(16);
DF.setGroupingUsed(假);
}
公共静态双固定有效数字增量(双输入,整数有效数字){
返回输入+固定有效数字量(输入,有效数字);
}
公共静态双固定有效数字递减(双输入,整数有效数字){
返回输入固定有效数字量(输入,有效数字);
}
公共静态双固定有效数字量(双输入,整数有效数字){
字符串inputStr=DF.format(输入);
int pointIndex=inputStr.indexOf('.');
int-digitsBeforePoint;
如果(点索引==-1){
pointIndex=inputStr.length();
digitsBeforePoint=inputStr.length();
}否则{
digitsBeforePoint=点索引;
如果(digitsBeforePoint==1&&inputStr.charAt(0)==0')digitsBeforePoint=0;
}
如果(significtdigitno,浮点运算无论如何都是不准确的。为什么你认为你需要这样做?这是可行的,但在IEEE754二进制浮点中会非常非常棘手。我的建议是通过BigDecimal路径。我有一个特殊的计算,需要增加/减少nu中的有效数字成员数。预期的“数字”为十进制,双精度实现为二进制。FP计算不仅存在精度问题(如@kayaman say),但表示法也有问题:并非每个值都存在于双域中。这不能四舍五入,或者不能通过四舍五入来实现。@YCF_L:除了使用正则表达式计算数量级之外,这很好。但是它显示了错误的值…0.12345必须是0.12346,依此类推。有些值是正确的,有些则不是。请检查r输出与问题的输出OK@Alexandr我们接近了,我将很快编辑我的答案我忘记了这个案例;)@Alexandr那么像0.123这样的案例中的0不算?抱歉,它仍然不起作用。检查答案中的输出值。与您的解决方案不起作用的案例:0.0012345->0.0012346
0.000123456789->0.000123466789
@Alexandr立即检查抱歉,您的解决方案不起作用。请使用0.01234567->>0.01测试您的解决方案234667
。请在编辑有问题的输出值之前检查您的解决方案。
public static final DecimalFormat DF = (DecimalFormat) NumberFormat.getNumberInstance(Locale.ENGLISH);
static {
DF.setMaximumFractionDigits(16);
DF.setGroupingUsed(false);
}
public static double fixedSignificantDigitIncrement(double input, int significantDigit){
return input+fixedSignificantDigitAmount(input, significantDigit);
}
public static double fixedSignificantDigitDecrement(double input, int significantDigit){
return input-fixedSignificantDigitAmount(input, significantDigit);
}
public static double fixedSignificantDigitAmount(double input, int significantDigit){
String inputStr = DF.format(input);
int pointIndex = inputStr.indexOf('.');
int digitsBeforePoint;
if(pointIndex==-1){
pointIndex=inputStr.length();
digitsBeforePoint=inputStr.length();
} else {
digitsBeforePoint = pointIndex;
if(digitsBeforePoint==1 && inputStr.charAt(0)=='0') digitsBeforePoint=0;
}
if(significantDigit<=digitsBeforePoint){
return Math.pow(10, digitsBeforePoint-significantDigit);
} else if(digitsBeforePoint==0){
++pointIndex;
for(;pointIndex<inputStr.length();pointIndex++){
if(inputStr.charAt(pointIndex)!='0') break;
}
return 1/Math.pow(10, significantDigit+(pointIndex-2));
}
return 1/Math.pow(10, significantDigit-digitsBeforePoint);
}