2016-06-11 24 views
4

Ich habe den folgenden sage Code, der sofort ausgeführt wird (weniger als eine Sekunde) und ich versuche, ihn in Java zu konvertieren (mithilfe der in Java integrierten BigInteger-Bibliothek). Aber ich bin nicht erfolgreich.Versucht, das System der Weisenzahlen für BigInteger zu verstehen

Kurz gesagt, I initialisiert N als BigInteger und delta als Doppel und um Leistung zu berechnen (BigInteger^double) I N zu BigDecimal (dh new BigDecimal(BigInteger)) umgewandelt und dann:

  1. ich benutzte this Ansatz, aber es ist zu langsam (sehr langsam).
  2. verwendete ich this Bibliothek aber ich verlor zu viel Präzision.
  3. Ich habe this Bibliothek verwendet, aber ich habe Überlauf Ausnahme.

N = 16260595201356777876687102055392856230368799478725437225418970788404092751540966827614883675066492383688147288741223234174448378892794567789551235835087027626536919406320142455677084743499141155821894102610573207343199194327005172833989486958434982393556326206485954223151805798621294965926069728816780985683043030371485847746616146554612001066554175545753760388987584593091716701780398711910886679925612838955858736102229719042291682456480437908426849734556856917891628730543729446245974891735371991588505429152639045721840213451875487038496578525189542369448895368117152818687795094021869963915318643663536132393791 
delta = 0.26 
X = 2*floor(N^delta) # in sage,^operator means exponentiation 
        # similar to ** operator in python 

print("X:" + str(x)) 

Ausgang:

X: 32803899270297070621193977210731234596426011189989730481205367370572340252530823123935195892838208219967066426399488721710159859316222019683979411877007525412864


Was ist der Zauber? Wie weise macht das? Wie man diesen Code in Java umwandelt (und ein ähnliches Ergebnis erhalten kann), sollte es eine Lösung geben.

+0

Grunde möchte ich BigInteger potenzieren zu verdoppeln. –

+0

In diesem Fall bin ich verwirrt über die Notwendigkeit einer Präzision, die über das hinausgeht, was man erhalten könnte, wenn man die sehr große ganze Zahl in ein "double" umwandelt und mit pow() potenziert, weil die Potenzierung zu einer nicht-ganzzahligen Potenz eine irrationale Zahl ergibt als Ergebnis. – Steve

+0

@Steve Ich habe es versucht (Link: http://pastebin.com/raw/BpGn83Sb), aber ich bekomme Unendlichkeit. –

Antwort

2

Sie können Ansatz 1 mit einer Problemumgehung verwenden. Das Problem ist, dass BigFunctions.ln() nicht sehr effektiv für Zahlen mit großen ganzzahligen Teil ist (Anzahl der Ziffern nach dem Komma). Als Workaround habe ich die Zahl so skaliert, dass sie höchstens eine Ziffer im ganzzahligen Teil enthielt, und dies später durch Hinzufügen von ln(10) * rescale * delta zum Argument exp() kompensiert.
Sie sollten auch beachten, dass die Verwendung von new BigDecimal(double) Konstruktor zu einem Verlust der Genauigkeit führt - lesen Sie die javadoc für die Erklärung. Stattdessen sollten Sie new BigDecimal(String) verwenden (besonders, wenn das Double von einem Konfigurationswert kommt) oder BigDecimal.valueOf(double).

BigInteger N = new BigInteger("16260595201356777876687102055392856230368799478725437225418970788404092751540966827614883675066492383688147288741223234174448378892794567789551235835087027626536919406320142455677084743499141155821894102610573207343199194327005172833989486958434982393556326206485954223151805798621294965926069728816780985683043030371485847746616146554612001066554175545753760388987584593091716701780398711910886679925612838955858736102229719042291682456480437908426849734556856917891628730543729446245974891735371991588505429152639045721840213451875487038496578525189542369448895368117152818687795094021869963915318643663536132393791"); 
double delta = 0.26; 

// this scale is sufficient to get the exact integer part 
// it is roughly equal to the number of digits in the result's integer part 
final int SCALE = 170; 
BigDecimal x = new BigDecimal(N); 
BigDecimal y = BigDecimal.valueOf(delta); 

int maxIntDigits = 1; 
int intDigits = x.precision() - x.scale(); 
int rescale = Math.max(intDigits - maxIntDigits, 0); 
BigDecimal rescaledX = x.scaleByPowerOfTen(-rescale); 

BigDecimal z = BigFunctions.exp(
     BigFunctions.ln(rescaledX, SCALE) 
       .add(BigFunctions.ln(BigDecimal.TEN, SCALE).multiply(BigDecimal.valueOf(rescale))) 
       .multiply(y), 
     SCALE) 
     .setScale(0, BigDecimal.ROUND_FLOOR) 
     .multiply(BigDecimal.valueOf(2)); 

System.out.println(z); 

Ausgang:

+0

Vielen Dank! Genial. –