如何增加 Java 中的固定有效数字?
How to increment fixed significant digit in Java?
我不确定 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 -> 0.0012346
123.5 -> 123.51
12.5 -> 12.501
0.000123456789 -> 0.000123466789
有没有固定有效数字递增/递减的解决方案?
编辑:
不准确的算术是可以的。 IE。如果我们将 12.5 变为 12.50100000000041 就可以了。
最小输入值为 0.00001。最大输入值为 100000.0.
increment/decrement 的最大有效数字为 5。
IE。增量后的最小输出值为 0.000010001
最高有效位到最低有效位的长度不超过10
P.S。在发布答案之前,请至少使用此问题中列出的所有示例编号测试您的解决方案。
我将检查所有答案以找到最有效的解决方案。最快的方法将被标记为正确方法。
希望对您有所帮助:
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+", "");
String rightPart = String.valueOf(number).replaceAll("^\d+\.(\d+)", "");
int left = leftPart.length();
int right = rightPart.length();
if (Integer.parseInt(leftPart) == 0) {
position = 6 + rightPart.replaceAll("^([0]*).*", "").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..................................");
}
备注
如果递增
,可以将add
改为subtract
输出
12345.0
12346.00000
..................................
1234567.0
1234667.00000
..................................
0.12345
0.12346
..................................
0.1
0.10001
..................................
0.0012345
0.0012346
..................................
123.5
123.51000
..................................
12.5
12.50100
..................................
1234500000.0000000012345
1234600000.0000000012345
..................................
我可以提出一个有效的方法:
- 计算给定数字的克拉数,例如:
1 -> 1, 152 -> 3, 123.65899 -> 8
- 你现在有两个案例,
size is >5 or <5
- 第一种情况:如果大小>5,则从您的号码中删除"comma"并将号码的大小保存在"comma"之后10**size 格式,例如:
12345.67 = 1234567 x 10**-2 , 0.1234567 = 1234567 x 10**-7
- 去掉"comma"后数字加1:
12345.67 = (1234567 + 1) x 10**-2 = 12345.68 , 0.99999 = (99999 + 1) x 10**-5 = 1.00000
- 第二种情况:如果大小小于 5,则添加零并将 10 的幂乘以负值,示例
5 = 50000 x 10**-4
- 与第一种情况相同加1并应用10**-x,示例:
1234 = 12340 x 10**-1 -> (12340 + 1) x 10**-1 = 1234.1
注意:您可以将此解决方案应用于除 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);
}
我不确定 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 -> 0.0012346
123.5 -> 123.51
12.5 -> 12.501
0.000123456789 -> 0.000123466789
有没有固定有效数字递增/递减的解决方案?
编辑:
不准确的算术是可以的。 IE。如果我们将 12.5 变为 12.50100000000041 就可以了。
最小输入值为 0.00001。最大输入值为 100000.0.
increment/decrement 的最大有效数字为 5。
IE。增量后的最小输出值为 0.000010001
最高有效位到最低有效位的长度不超过10
P.S。在发布答案之前,请至少使用此问题中列出的所有示例编号测试您的解决方案。 我将检查所有答案以找到最有效的解决方案。最快的方法将被标记为正确方法。
希望对您有所帮助:
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+", "");
String rightPart = String.valueOf(number).replaceAll("^\d+\.(\d+)", "");
int left = leftPart.length();
int right = rightPart.length();
if (Integer.parseInt(leftPart) == 0) {
position = 6 + rightPart.replaceAll("^([0]*).*", "").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..................................");
}
备注
如果递增
,可以将add
改为subtract
输出
12345.0
12346.00000
..................................
1234567.0
1234667.00000
..................................
0.12345
0.12346
..................................
0.1
0.10001
..................................
0.0012345
0.0012346
..................................
123.5
123.51000
..................................
12.5
12.50100
..................................
1234500000.0000000012345
1234600000.0000000012345
..................................
我可以提出一个有效的方法:
- 计算给定数字的克拉数,例如:
1 -> 1, 152 -> 3, 123.65899 -> 8
- 你现在有两个案例,
size is >5 or <5
- 第一种情况:如果大小>5,则从您的号码中删除"comma"并将号码的大小保存在"comma"之后10**size 格式,例如:
12345.67 = 1234567 x 10**-2 , 0.1234567 = 1234567 x 10**-7
- 去掉"comma"后数字加1:
12345.67 = (1234567 + 1) x 10**-2 = 12345.68 , 0.99999 = (99999 + 1) x 10**-5 = 1.00000
- 第二种情况:如果大小小于 5,则添加零并将 10 的幂乘以负值,示例
5 = 50000 x 10**-4
- 与第一种情况相同加1并应用10**-x,示例:
1234 = 12340 x 10**-1 -> (12340 + 1) x 10**-1 = 1234.1
注意:您可以将此解决方案应用于除 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);
}