Mit sehr großen Werten rechnen



  • Hallo,
    ich habe folgendes Problem. Ich "spiele" gerade auf enigmagroup.org die JavaScript Missionen und bin inzwischen bei der letzten angekommen.
    Das Passwort berechnet sich dabei aus dem aktuellen Jahr, man kommt also nur weiter wenn man sich zufällig gerade in diesem Jahr befindet oder das gesuchte Jahr herausfindet und es der URL anhängt. Hier der Code:

    date = new Date();
    year = date.getYear();
    pass = 1337;
    
    for(i = 1; i <= year; i++){
      pass += year * i * year;
    }
    
    if(pass == 318338237039211050000){
      alert("Good job!");
      window.location.href = year + ".php";
    }
    else{
      alert("Sorry, did you fail already?!");
      window.location.href = "./index.php";
    }
    

    Ich habe nun versucht mit diesem Code eine Lösung in C++ zu schreiben und bin daran gescheitert.
    Ich habe einfach die Jahre hochgezählt und immer pass berechnet und dann mit der langen Zahl (wie in der Routine) verglichen.
    Das Problem ist jedoch (und das ist mir erst ziemlich spät eingefallen), dass die Zahl für jeden Datentyp zu groß ist 😞

    Ich dachte mir dann, ich könnte die Zahl einfach durch z.B. 1.000.000 dividieren und die restlichen Zahlen als Nachkommestellen mitführen.
    Allerdings kommt dabei folgendes raus:

    double test=31833823703921106.0000;
    printf ("%f", test);
    

    Ausgabe:

    31833823703921104.000000
    

    Wie wird denn aus der ...6,0... eine ...4,0... ?
    Hat irgendjmd eine Idee wie ich mein Problem lösen könnte?

    Grüße



  • Floats sind nicht exakt. Sie sind z.B. für Messwerte brauchbar, weil sie verschiedene Größenbereiche annehmen können (z.B. sowohl 10^-6 als auch für 10^8) und in diesem Bereich annähernd genaue Ergebnisse liefern.

    Wenn es exakt sein soll, müssen integer ran.

    Wenn long long bzw. std::int64_t nicht reichen, nimm eine bigint library oder bastel dir selber irgendwelche Konstrukte aus mehreren integern.



  • Das Rätsel geht nicht auf. Die Lösung wird 158847 sein, aber mit der Eingabe kommt, wenn man genau rechnet, als Ergebnis 318338237039211261689 heraus. Das liegt in der Größenordnung von 268 und passt in keinen der üblichen Datentypen (inklusive long double auf den meisten gängigen Plattformen) hinein.

    Dem fällt auch der Javascript-Code zum Opfer -- er rechnet ja selbst nicht genau. Der Autor verlässt sich auf ein bestimmtes Rundungsverhalten in der Javascript-Engine, wodurch es mehr oder weniger zur Glückssache wird, ob die richtige Lösung das Rätsel auch lösen wird. Geh am besten direkt auf 158847.php. Oder lass es sein; so richtig viel Plan schien der Autor der Rätsel nicht zu haben, als er sie geschrieben hat, und ich habe meine Zweifel, dass sich die Reise lohnt.



  • Vielen Dank für die Antworten.
    Das war mir nicht bewußt aber nun hab ich ja, auch wenn es nun nicht funktioniert hat, trotzdem was draus gelernt! 🙂
    Und die Lösung 158847 ist tatsächlich richtig!


Log in to reply