[英]Cutting of the first 9 digits
Alright I am trying to solve a challenge one of my friends gave me to do, well I've manged to cut the last 9 digits out of a BigInteger
well I had a way to cut-off the first 9 but it was so slow, it was taking too long. 好吧,我正在尝试解决我的一个朋友给我做的一个难题,好吧,我已经设法从
BigInteger
删掉了最后9位数字,我有办法删掉前9个数字,但是太慢了,花了太长时间。
The reason I need the first 9 and the last 9 is because I am looking for a BigInteger
where the first and last are pandigital. 我需要前9个和后9个的原因是因为我正在寻找第一个和最后一个为pandigital的
BigInteger
。
If you do not understand what I mean say we have n = new BigInteger("123456789987654321")
well I need to get the "123456789" and the "987654321" seperately, and I do NOT want to convert the BigInteger to a string because that's a VERY slow process. 如果你不明白我的意思说,我们有
n = new BigInteger("123456789987654321")
好,我需要获得“123456789”和“987654321” seperately,我不想给的BigInteger转换为字符串,因为这是一个非常缓慢的过程。
I am going for speed here, I am just stumped on this solution. 我在这里追求速度,我只是对这个解决方案感到困惑。 I've heard something about using the Golden Ratio?
我听说过有关黄金分割率的信息吗? Here is my code if you're interested.
如果您有兴趣,这是我的代码。
import java.math.BigInteger;
public class Main {
public static void main(String...strings)
{
long timeStart = System.currentTimeMillis();
fib(350_000);
long timeEnd = System.currentTimeMillis();
System.out.println("Finished processing, time: " + (timeEnd - timeStart) + " milliseconds.");
}
public static BigInteger fib(int n)
{
BigInteger prev1 = BigInteger.valueOf(0), prev2 = BigInteger.valueOf(1);
for (int i = 0; i < n; i++)
{
// TODO: Check if the head is pandigital as well.
BigInteger tailing9Digits = tailing9Digits(prev1);
boolean tailPandigital = isPanDigital(tailing9Digits);
if (tailPandigital)
{
System.out.println("Solved at index: " + i);
break;
}
BigInteger savePrev1 = prev1;
prev1 = prev2;
prev2 = savePrev1.add(prev2);
}
return prev1;
}
public static BigInteger leading9Digits(BigInteger x)
{
// STUCK HERE.
return null;
}
public static BigInteger tailing9Digits(BigInteger x)
{
return x.remainder(BigInteger.TEN.pow(9));
}
static BigInteger[] pows = new BigInteger[16];
static
{
for (int i = 0; i < 16; i++)
{
pows[i] = BigInteger.TEN.pow(i);
}
}
static boolean isPanDigital(BigInteger n)
{
if (!n.remainder(BigInteger.valueOf(9)).equals(BigInteger.ZERO))
{
return false;
}
boolean[] foundDigits = new boolean[9];
boolean isPanDigital = true;
for (int i = 1; i <= 9; i++)
{
BigInteger digit = n.remainder(pows[i]).divide(pows[i - 1]);
for (int j = 0; j < foundDigits.length; j++) {
if (digit.equals(BigInteger.valueOf(j + 1)) && !foundDigits[j])
{
foundDigits[j] = true;
}
}
}
for (int i = 0; i < 9; i++)
{
isPanDigital = isPanDigital && foundDigits[i];
}
return isPanDigital;
}
}
BigInteger
isn't something I'd recommend using if you care at all about speed. 如果您完全关心速度,我不建议您使用
BigInteger
。 Most of its methods are poorly-implemented, and this typically results in very slow code. 它的大多数方法执行不佳,通常会导致代码非常慢。
There's a divide-and-conquer trick for division and radix conversion that you might find helpful. 对于除法和基数转换,有一个分而治之的技巧,您可能会发现有帮助。
First, BigInteger
's multiply()
is quadratic. 首先,
BigInteger
的multiply()
是二次的。 You'll need to work around that, otherwise these divide-and-conquer tricks won't lead to any speedup. 您将需要解决此问题,否则这些分而治之的技巧将不会导致任何提速。 Multiplication via the fast Fourier transform is reasonably fast and good.
通过快速傅立叶变换的乘法相当快且良好。
If you want to convert a BigInteger
to base 10, break it in half (bitwise) and write it as a * 256^k + b.
如果要将
BigInteger
转换为10,则将其对半分割(按位)并将其写为a * 256^k + b.
One thing you can do is convert a
and b
to base-10 recursively, then convert 256^k
to decimal by repeated squaring, and then, in base 10, multiply a
by 256^k
and add b
to the result. 您可以做的一件事是将
a
和b
递归转换为10的基数,然后通过重复平方将256^k
转换为十进制,然后以10为基数,将a
乘以256^k
然后将b
加到结果中。 Also, since you're only interested in the first few digits, you might not even need to convert b
if the first few digits of a * 256^k
can't possibly be influenced by adding something as small as b
. 此外,由于您只对前几位有兴趣,你可能甚至不需要转换
b
如果前几位a * 256^k
不可能通过增加小东西的影响b
。
A similar trick works for division. 类似的技巧适用于除法。
You can do bit-shifting and extraction using the toByteArray()
method. 您可以使用
toByteArray()
方法进行位移和提取。
Maybe this is not too fast but at least it's simple 也许这不太快,但至少很简单
BigInteger n = new BigInteger("123456789987654321");
BigInteger n2 = n.divide(BigInteger.TEN.pow(new BigDecimal(n).precision() - 9));
BigInteger n1 = n.remainder(new BigInteger("1000000000"));
System.out.println(n1);
System.out.println(n2);
output 产量
987654321
123456789
Well I believe this is what you need: 好吧,我相信这是您需要的:
import java.math.BigInteger;
public class PandigitalCheck {
public static void main(String[] args) {
BigInteger num = new BigInteger("12345678907438297438924239987654321");
long timeStart = System.currentTimeMillis();
System.out.println("Is Pandigital: " + isPandigital(num));
long timeEnd = System.currentTimeMillis();
System.out.println("Time Taken: " + (timeEnd - timeStart) + " ms");
}
private static boolean isPandigital(BigInteger num) {
if (getTrailing9Digits(num).compareTo(getLeading9Digits(num)) == 0) {
return true;
}
return false;
}
private static BigInteger getLeading9Digits(BigInteger num) {
int length = getBigIntLength(num);
BigInteger leading9 = BigInteger.ZERO;
for (int i = 0; i < 9; i++) {
BigInteger remainder = num.divide(BigInteger.TEN.pow(length - 1 - i));
leading9 = leading9.add(remainder.multiply(BigInteger.TEN.pow(i)));
num = num.remainder(BigInteger.TEN.pow(length - 1 - i));
}
return leading9;
}
private static int getBigIntLength(BigInteger num) {
for (int i = 1; ; i++) {
if (num.divide(BigInteger.TEN.pow(i)) == BigInteger.ZERO) {
return i;
}
}
}
private static BigInteger getTrailing9Digits(BigInteger num) {
return num.remainder(BigInteger.TEN.pow(9));
}
}
The output is: 输出为:
Is Pandigital: true
Time Taken: 0 ms
Does it fit the bill? 它符合要求吗?
I'm newbie for java, I'm converting BigInteger to String only but it's little bit fast as your code 我是Java的新手,我只是将BigInteger转换为String,但它的代码速度却很快
import java.math.BigInteger;
public class Main {
public static void main(String args[])
{
long timeStart = System.currentTimeMillis();
String biStr = new BigInteger("123456789987654321").toString();
int length=(biStr.length())/2;
String[] ints = new String[length];
String[] ints2 = new String[length];
for(int i=0; i<length; i++) {
int j=i+length;
ints[i] = String.valueOf(biStr.charAt(i));
ints2[i] = String.valueOf(biStr.charAt(j));
System.out.println(ints[i] +" | "+ints2[i]);
}
long timeEnd = System.currentTimeMillis();
System.out.println("Finished processing, time: " + (timeEnd - timeStart) + " milliseconds.");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.