Problem mit der Übersetzung eines C++ Source Codes

nop0x90

Mitglied
Hi,
nach nun einiger Zeit brauche ich mal wieder eure kompetente Hilfe ^^


Das Problem ist folgender C++ Source Code
Code:
unsigned __int64 out;
void Test(unsigned __int64 input)
{
 out = ((input ^ 0x00000005DEECE66Dui64) & 0x0000FFFFFFFFFFFFui64);
}
So wie er hier steht gibt er der Variable out, nach Aufruf mit einem Parameter, der den Wert 1147 hat, den Wert 25214902806.
Meine Lösungsansetze in PHP möchte ich euch ersparen, denn ich komme auf die wildesten Sachen (-270675368, 825302713, 55489, 97).

Falls also jemand von euch das bisschen Source Code in PHP übersetzen kann, oder mir wenigstens Hilfestellung (Tipps) geben könnte, würde ich mich über eine Antwort dieser Person sehr freuen :)


Danke aber schonmal fürs Lesen
 
Okay, das Problem sieht wohl wie folgt aus: Der Integer ist zu klein.

Gib mal die Konstante PHP_INT_MAX aus, diese wird wohl kleiner sein als der von Dir erwartete Wert. Entsprechend gibt es einen Ueberlauf.
Zudem scheinen AND, OR, etc. grundsaetzlich nur mit Integer-Werten zu arbeiten, sodass selbst das erzwingen von Float-Variablen nicht zum gewuenschten Erfolg fuehrt.

Uebrigens, auf einem 64-Bit-System, wo ja der Integer entsprechend breiter ist als auf einem 32-Bit-System, funktioniert der Code
PHP:
$resval=(($inval ^ $xorval) & $andval);
wunderbar.

Eine Loesung, also fuer 32-Bit-Systeme, sehe ich hier im Moment nicht.
 
Hi Dennis,

danke für Deine Antwort! Die hat mir schon sehr geholfen. An einen Speicherüberlauf habe ich kurz auch gedacht, wusste aber zu dem Zeitpunkt noch gar nicht wirklich was das ist (so lächerlich das klingt), deswegen bin ich darauf nicht weiter eingegangen. Nun habe ich mir etwas mehr Wissen angeeignet und bin zu dem Entschluss gekommen, dass ich nicht ohne die GMP (GNU Multiple Precision) Erweiterung auskommen werde. Ich habe eine provisorische Klasse geschrieben, die auch schon teilweise funktioniert. Ich komme nun zum gewünschten Ergebnis von 25214902806, doch der zweite Teil des C++ Source Codes, der mir Probleme bereitet, hat es richtig in sich.

Teil aus der C++ Klasse:
Code:
	double NextDouble()
	{
		unsigned __int64 z1;

		this->seed = (((this->seed * 0x00000005DEECE66Dui64) + 0x000000000000000Bui64) & 0x0000FFFFFFFFFFFFui64);
		z1         = (this->seed >> 22); z1 <<= (27);
		this->seed = (((this->seed * 0x00000005DEECE66Dui64) + 0x000000000000000Bui64) & 0x0000FFFFFFFFFFFFui64);
		z1        += (this->seed >> 21);

		return ((double) z1 / (double) 0x0020000000000000ui64);
	}
Meine provisorische PHP Übersetzung ("NextDouble", aka der problematische Teil, heißt hier "getNext"):
PHP:
<?php
class nRand
{
  var $gSeed = null;
  
  function nRand($uInit)
  {
    if(!function_exists(gmp_init))
      return false;
    
    $vSeed = gmp_init($uInit);
    $vXOR  = gmp_init((string) 25214903917);   // 0x00000005DEECE66D
    
    $this->gSeed = gmp_xor($vSeed, $vXOR);
  }
  
  function getSeed()
  {
    return (float) gmp_strval($this->gSeed);
  }
  
  function getNext()
  {
    if($this->gSeed == null)
      return false;
    
    $t1 = gmp_init((string) 9007199254740992); // 0x0020000000000000
    $t2 = gmp_init((string) 25214903917);      // 0x00000005DEECE66D
    $t3 = gmp_init((string) 11);               // 0x000000000000000B
    $t4 = null;
    
    $this->gSeed   = gmp_add(gmp_mul($this->gSeed, $t2), $t3);
    $t4            = (gmp_strval($this->gSeed) >> 22);
    $t4          <<= 27;                       // Hier wird der Wert negativ!
    $this->gSeed   = gmp_add(gmp_mul($this->gSeed, $t2), $t3);
    $t4           += (gmp_strval($this->gSeed) >> 21);
    
    return gmp_strval(gmp_div_q(gmp_init($t4), $t1));          
  }
}
?>

Aufruf und Problem:
PHP:
<?php
//...
$a = new nRand(1147);
echo $a->getSeed() . "\n";
echo $a->getNext(); //Sollte den Wert 0.631443 ausgeben
?>

Hoffe, dass Du mir helfen kannst, denn ich kenne keine GMP Funktion die das "<<=" ersetzen könnte.

Bis dann!
 
PHP:
    $t1 = gmp_init((string) 9007199254740992); // 0x0020000000000000
Das geht ziemlich sicher schief. Diese Konstante passt nicht mehr in einen 32-Bit-Integer und wird von PHP deswegen als Fließkommazahl interpretiert. Schreib das ganze doch einfach gleich als String, in dem Falle also
PHP:
gmp_init("0x0020000000000000");
(ebenso an allen anderen Stellen!).

PHP:
    $this->gSeed   = gmp_add(gmp_mul($this->gSeed, $t2), $t3);
Hier hast du das binäre Und vergessen.

PHP:
    $t4            = (gmp_strval($this->gSeed) >> 22);
    $t4          <<= 27;                       // Hier wird der Wert negativ!
Ein Bitshift um x Stellen nach links/rechts entspricht nichts anderem als einer Multiplikation mit/Division durch 2^x.

PHP:
    return gmp_strval(gmp_div_q(gmp_init($t4), $t1));
Auf diese Weise wird immer 0 rauskommen, da hier eine Ganzzahldivision durchgeführt wird. Besser wäre also
PHP:
return gmp_strval($t4) / gmp_strval($t1)

Grüße,
Matthias
 
Sorry, mein C++ ist ein wenig beschraenkt, und zudem noch arg eingerostet. Was ist <<, ein Links-Shift?

Also in der Dokumentation zur GMP-Extension konnte ich jetzt nichts von einem Shift sehen. PHP selbst kann zwar shiften, dort duerftest Du dann aber wohl wieder in die gleiche Einschraenkung rennen wie es bereits zuvor der Fall war.
 
Dennis: Ja, das ist ein Links-Bitshift. Wobei $t4 <<= 27; gleich $t4 = $t4 << 27; ist.
Matthias: Mist, ich wusste gar nicht, dass man dort sogar hexadezimale Werte angeben kann. Und das AND habe ich komplett vergessen!

Großes Dankeschön an euch!


OffTopic: Ich fühle mich richtig komisch, wenn ich eure Benutzernamen sehe, dass ich mich nicht traue meinen richtigen Namen zu verwenden ^^
 
Zurück