2017-08-09 52 views
1

最近我开始在Java中使用GMP,通过一个包装(从这个Github回购)对于涉及极端数字的一些计算。
“极端”,我的意思是有时数字超过700万位数。如何将此方法更改为返回字符串列表而不是字符串?

一切工作绝对正常,但我打算做一个计算估计会产生一个大约80亿位数的数字,尽管GMP库可以处理这个问题,并且执行代码的机器具有足够的内存,问题是以10为基数获取此数字的唯一方法是通过方法toString(int base)(或简单地toString())返回包含指定基数的数字的字符串,但由于字符串依赖于一个char数组来保存字母,如果我没有弄错,它将不能保存8亿个字母,因为最大阵列大小为2^32-6

从Java可惜APPART我不知道任何其他语言不够好......

因此,我的问题是,如何能在GMP包装(也可能是本地代码),以改变以返回List<String>而不是单数String与数字? 如果这太难或者甚至不可能,那么在Java中有没有其他的选择可以处理大的数字?

谢谢!

+2

@azurefrog同样的问题,80亿个数字不能转换为一个'String'。我想知道OP计划如何处理这80亿位数字。 –

+0

回答如何在不知道代码现在的样子的情况下修改某些代码有点困难。 – tradeJmark

+0

@tradeJmark如果你引用我的代码,修改它并不能解决问题,因为屏障是位于我的代码和上面提到的GMP包装器之间的字符串。如果这种方法可以以某种方式改变,那么它将一切正常。 –

回答

1

我不知道电话号码的类型,所以假设的BigInteger。尝试这个。

UPDATE:创建变量DIGITS_PER_STRNG,因此您可以控制每个String项目的位数。

class Sample { 

    private static void test_num_to_string() { 
     List<String> list = intToStringList(sampleBigInt()); 
    } 

    private static final int DIGITS_PER_STRNG = 10; // DIGITS_PER_STRNG < Integer.MAX_VALUE (= max String length) 
    private static final BigInteger DIVIDER = BigInteger.valueOf(10); 

    private static List<String> intToStringList(BigInteger i) { 
     List list = new ArrayList(); 

     while (i.compareTo(BigInteger.ZERO) > 0) { 
      String str = ""; 
      for (int j = 0; j < DIGITS_PER_STRNG; j ++) { 
       BigInteger[] divideAndRemainder = i.divideAndRemainder(DIVIDER); 
       str = str + String.valueOf(divideAndRemainder[1]); 
       i = divideAndRemainder[0]; 
      } 
      list.add(str); 
      System.out.println(str); 
     } 

     return list; 
    } 

    private static BigInteger sampleBigInt() { 
     BigInteger bigInt = BigInteger.valueOf((int) Math.pow(2, 10000)); 
     int i; 
     for (i = 0; i < 10; i ++) { 
      bigInt = bigInt.multiply(bigInt); 
     } 
     return bigInt; 
    } 
} 
+0

感谢您的回答,但是当BigInteger在处理像上面那样的巨大数字时会出现一些其他的BigDisadvantages,并且我注意到,当用aprox 。 4亿位数字与另一个大数字(7位数字)它进入一个奇怪的死锁状态,所以考虑到这一点,我使用GMP的性能,这基本上只是本地代码,而不是Java代码...虽然你的答案不解决我的问题,我认为它应该留在这里寻求与BigInteger类似的其他人,因为它确实是非常丰富的: - ) –

+0

更新:我意识到我是多么愚蠢,我可以很容易地将此​​代码适应GMP,所以我做了!谢谢你真的帮助。所产生的字符串是以10为底的数字,但这很容易修复,只需将其反转即可!现在我的问题是,我如何确定在转换为字符串期间用于分割数字的正确常量?在你的例子中它是'10000000000',但我不知道如何优化:S 再次,谢谢! –

+0

好的,我编辑了我的帖子。 如果您不关心性能,只需调用: 'DIGITS_PER_STRING = Integer.MAX_VALUE' 但是当目标BigInteger足够大时,您可以考虑通过调用 DIGUST_PER_STRING = Integer.MAX_VALUE/x' 'private static final BigInteger DIVIDER = BigInteger.valueOf(10).pow(x);' 其中'x'大约10000000或更多。 (它应该随着目标变大而变大。) 在我的电脑上,'.pow(100000000)'永不结束(1分钟是我的忍耐极限),供您参考。 对不起,我英文很差。希望它能帮助你 – Yuta

0

编辑:我做了连接,GMP对象不支持这些普通的按位运算符,但我看到他们有适当的方法。这只是逻辑;您必须将其转换为您的库

使用按位运算符将您的大数切分为Java可以消化的更小的位块。然后,将它们分别转换为字符串。 第一块(你需要定义MAX_STRING_SIZE

MAX_STRING_SIZE & largeNumber 

二大块:

MAX_STRING_SIZE & (largeNumber >> numbBits(MAX_STRING_SIZE)) // shift right by number of (used) bits in MAX_STRING_SIZE, so it will be aligned for this calculation 

三大块:

MAX_STRING_SIZE & (largeNumber >> 2*numbBits(MAX_STRING_SIZE)) // shift twice 

这种模式可以被压缩成一个for循环喜欢 - 明智(随着转换为字符串):

ArrayList<String> strings = new ArrayList<String>(); 
while (largeNumber > MAX_STRING_SIZE) { 
    largeNumber = largeNumber >> numbBits(MAX_STRING_SIZE)) // shift again 
    strings.add(Integer.toString(MAX_STRING_SIZE & largeNumber)); // this value will be an integer 
} 

而且numbBitsthis answer定义(我给它改名为清楚起见):

int numbBits(int value) { 
    return Integer.SIZE-Integer.numberOfLeadingZeros(value); 
} 
+1

我要试一试,但我不确定它是否会会产生正确的数字。例如,假设我有数字:'1101110101',它是以#10为基数的'885'。使用'MAX_STRING_SIZE'来表示'2'(numBits ='2'),它会将位字切割为下面的块: '11''01''11''01''01'把这些字符串分别通过Integer.toString()产生: '2''1''2''1''1' - > 21211 which是不是基地10这个基地的2号:( –

+0

是的,刚刚实施它,实际上在基地10产生的数字是不正确:(也在你的循环中,你的意思是拳头得到低位字,然后转移数字或因为目前你在移动之前,最低的MAX_STRING_SIZE位丢失了...... –

+0

@fill͡pant͡你是对的,但有一个问题:'Integer.toString'如何变成'11'(二进制)进入''2''?不是''3''吗? – clabe45

相关问题