Kapitel 12

Alle Codedateien dieses Kapitels herunterladen

12_3_SchweigenIstGold.cpp

Datei herunterladen

/*
 * Lösung für Übung 12.3 - Schweigen ist Gold
 *
 * Basiert auf 12_2_PiBerechnen.cpp, hinzugefügt wurde die Stelle, die mit
 * #1 markiert ist
 *
 * Die eleganteste Lösung ist mit dem Modulo-Operator %. Sie können aber auch
 * alternativ eine eigene Zählvariable hochzählen.
 */
#include <atomic>
#include <iomanip>
#include <iostream>
#include <string>
#include <thread>

int main()
{
  std::cout << "Beenden mit der Entertaste" << std::endl;
  // Möglichst viele Nachkommastellen ausgeben:
  std::cout << std::setprecision(15);

  // Zwei atomare Variablen zum Steuern des Threads
  std::atomic<bool> active = true;
  std::atomic<double> result = 0;

  std::thread leibniz([&]() {
    // Diese Implementierung nutzt die Leibnitz-Formel
    double sign = 1;  // Vorzeichen (+1 oder -1)
    double pi = 0;
    double denominator = 1;
    while (active)
    {
      pi = pi + sign * (4 / denominator);
      // Vorzeichen umdrehen
      sign = -sign;
      // Teiler um zwei erhöhen
      denominator += 2;

      // #1 Die Ausgabe auf gewisse Werte beschränken. Der Modulo-Operator %
      // ist nicht für double Zahlen verfügbar, daher casten wir vorher in einen long long,
      // der ebenfalls sehr große Zahlen beinhalten kann.
      // Da die Variable denominator immer um zwei erhöht wird, testen wir auf 40 Millionen,
      // um die Ausgabe wie erwünscht alle 20 Millionen Iterationen zu erhalten.
      // Da denominator immer ungerade ist, testen wir auf die 1
      if (static_cast<long long>(denominator) % 40000000 == 1)
      {
        std::cout << "\rStatus (" << denominator << "): "
          << pi;
      }
    }
    // Ergebnis in der atomaren Variable speichern
    result = pi;
  });

  // Im Haupt-Thread derweil auf die Entertaste warten
  std::string tmp;
  std::getline(std::cin, tmp);
  // Enter wurde gedrückt. Nun den Thread herunterfahren
  active = false;
  leibniz.join();
  std::cout << "\rEndresultat: " << result << std::endl;
  return 0;
}