我需要一个大整数的小数位数。例如:
99
返回2
1234
返回4
9999
返回4
12345678901234567890
返回20
我需要对biginger
和184948
十进制数字及更多数字执行此操作。我如何快速且可扩展地完成这项工作?
转换为字符串的方法很慢:
public String getWritableNumber(BigInteger number) {
// Takes over 30 seconds for 184948 decimal digits
return "10^" + (number.toString().length() - 1);
}
这种10倍循环的方法更慢:
public String getWritableNumber(BigInteger number) {
int digitSize = 0;
while (!number.equals(BigInteger.ZERO)) {
number = number.divide(BigInteger.TEN);
digitSize++;
}
return "10^" + (digitSize - 1);
}
有没有更快的方法?
我认为可以使用bitLength()获得log2值,然后将基数改为10。
然而,结果可能错了一位数,所以这只是一个近似值。
然而,如果这是可以接受的,你总是可以给结果加1,并将其限制为最多。或者,减去1,至少得到。
这看起来很有效。我还没有运行详尽的测试,也没有运行任何时间测试,但它似乎有一个合理的运行时间。
public class Test {
/**
* Optimised for huge numbers.
*
* http://en.wikipedia.org/wiki/Logarithm#Change_of_base
*
* States that log[b](x) = log[k](x)/log[k](b)
*
* We can get log[2](x) as the bitCount of the number so what we need is
* essentially bitCount/log[2](10). Sadly that will lead to inaccuracies so
* here I will attempt an iterative process that should achieve accuracy.
*
* log[2](10) = 3.32192809488736234787 so if I divide by 10^(bitCount/4) we
* should not go too far. In fact repeating that process while adding (bitCount/4)
* to the running count of the digits will end up with an accurate figure
* given some twiddling at the end.
*
* So here's the scheme:
*
* While there are more than 4 bits in the number
* Divide by 10^(bits/4)
* Increase digit count by (bits/4)
*
* Fiddle around to accommodate the remaining digit - if there is one.
*
* Essentially - each time around the loop we remove a number of decimal
* digits (by dividing by 10^n) keeping a count of how many we've removed.
*
* The number of digits we remove is estimated from the number of bits in the
* number (i.e. log[2](x) / 4). The perfect figure for the reduction would be
* log[2](x) / 3.3219... so dividing by 4 is a good under-estimate. We
* don't go too far but it does mean we have to repeat it just a few times.
*/
private int log10(BigInteger huge) {
int digits = 0;
int bits = huge.bitLength();
// Serious reductions.
while (bits > 4) {
// 4 > log[2](10) so we should not reduce it too far.
int reduce = bits / 4;
// Divide by 10^reduce
huge = huge.divide(BigInteger.TEN.pow(reduce));
// Removed that many decimal digits.
digits += reduce;
// Recalculate bitLength
bits = huge.bitLength();
}
// Now 4 bits or less - add 1 if necessary.
if ( huge.intValue() > 9 ) {
digits += 1;
}
return digits;
}
// Random tests.
Random rnd = new Random();
// Limit the bit length.
int maxBits = BigInteger.TEN.pow(200000).bitLength();
public void test() {
// 100 tests.
for (int i = 1; i <= 100; i++) {
BigInteger huge = new BigInteger((int)(Math.random() * maxBits), rnd);
// Note start time.
long start = System.currentTimeMillis();
// Do my method.
int myLength = log10(huge);
// Record my result.
System.out.println("Digits: " + myLength+ " Took: " + (System.currentTimeMillis() - start));
// Check the result.
int trueLength = huge.toString().length() - 1;
if (trueLength != myLength) {
System.out.println("WRONG!! " + (myLength - trueLength));
}
}
}
public static void main(String args[]) {
new Test().test();
}
}
在我的Celeron M笔记本电脑上花了大约3秒,所以在一些像样的装备上应该会达到2秒以下。
下面是一个基于Dariusz答案的快速方法:
public static int getDigitCount(BigInteger number) {
double factor = Math.log(2) / Math.log(10);
int digitCount = (int) (factor * number.bitLength() + 1);
if (BigInteger.TEN.pow(digitCount - 1).compareTo(number) > 0) {
return digitCount - 1;
}
return digitCount;
}
以下代码测试数字1、9、10、99、100、999、1000等,一直测试到一万位:
public static void test() {
for (int i = 0; i < 10000; i++) {
BigInteger n = BigInteger.TEN.pow(i);
if (getDigitCount(n.subtract(BigInteger.ONE)) != i || getDigitCount(n) != i + 1) {
System.out.println("Failure: " + i);
}
}
System.out.println("Done");
}
这可以在一秒钟内检查具有
184,948
十进制数字和更多数字的BigIntger
。
问题内容: 我需要计算的小数位数。例如: 退货 退货 退货 退货 我需要做的这 一个与十进制数字多。 我该如何快速且可扩展? 在 转换到字符串的 方法是缓慢的: 这种 按十个循环进行循环的 方法甚至更慢: 有没有更快的方法? 问题答案: 这看起来像在工作。我还没有进行详尽的测试,也没有进行任何时间的测试,但似乎运行时间合理。 在我的Celeron M笔记本电脑上花了大约3秒钟,因此它在某些不错的工
我正在尝试在旁边使用值方法。 不幸的是,编译器说不兼容的类型。 如果我将s更改为s,它仍然不喜欢它。
问题内容: 用MySQL计算中位数的最简单方法(希望不是太慢)是什么?我一直在寻找均值,但是我很难找到一种简单的计算中位数的方法。现在,我将所有行返回给PHP,进行排序,然后选择中间行,但是肯定必须有一个简单的方法可以在单个MySQL查询中完成。 示例数据: 排序给出,因此中位数应为,而其中== 。 问题答案: 在MariaDB / MySQL中: 史蒂夫·科恩(Steve Cohen)指出,在第
我试图使用值在C#中实现以下Java函数,以便不再适用64位限制。作为一项健全性检查,我将使用的原始函数也转换为C#代码。然而,问题是,使用的版本工作时,使用的版本并不总是返回相同的结果。 C#中原始函数的实现。 而不是像原始的Java代码那样打印所有的值,我打算使用它们,这样我就可以单独返回每个值。 在组合学中,使用choose函数可以很容易地验证生成的数字集合是否具有正确的值数: 从52张扑克
本文向大家介绍C#中的扩展方法,包括了C#中的扩展方法的使用技巧和注意事项,需要的朋友参考一下 扩展方法是静态方法,就像它们是扩展类型的实例方法一样被调用。使用扩展方法,您可以将方法添加到现有类型中,而无需创建新的派生类型,重新编译或修改原始类型。 以下是我们创建的扩展方法。 让我们看一个使用扩展方法的例子。 示例 输出结果
本文向大家介绍Laravel框架中扩展函数、扩展自定义类的方法,包括了Laravel框架中扩展函数、扩展自定义类的方法的使用技巧和注意事项,需要的朋友参考一下 一、扩展自己的类 在app/ 下建立目录 libraries\class 然后myTest.php 类名格式 驼峰 myTest 在 app/start/global.php 用 make 载入 二、扩展自己的函数 在app/ 下建立目录