Rechenautomat mit Double Zufallszahlen

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Kilian_98.

    Rechenautomat mit Double Zufallszahlen

    Hallo!

    Wir machen gerade in der Schule eine Übung zum Thema Schleifen, und sollen einen "Rechenautomat" erstellen.

    Mit Int32 funktioniert es ohne Probleme, aber wenn man die Zufallszahlen als Double erstellen lässt, kommt es doch öfters vor, dass das Ergebnis angeblich falsch sei.

    Die Lösung des Programms kam so vom Lehrer, ich habe nur etwas mehr WriteLines eingefügt um die Ausgabe genauer zu sehen.

    Meine Frage ist nun, was genau in dem Code diesen "Fehler" verursacht. Ist es die Art und Weise wie die Zufallszahlen erstellt werden? Oder die "Runden"-Funktion? Oder doch etwas anderes?
    Und mich würde interessieren, wie man es richtig macht mit Double.

    Vielen Dank schon mal für die Hilfe.

    Hier noch der Code:

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.Console
    3. ' Es wird eine zufällige Rechenaufgabe gestellt.
    4. ' Der Benutzer muss das richtige Ergebnis eingeben.
    5. ' Die Aufgabe wird solange wiederholt, bis das Ergebnis stimmt
    6. Module Module1
    7. Sub Main()
    8. Do
    9. Rechenautomat(2, 10) ' Ruft die Aufgabe in den Grenzen 1-10 auf
    10. WriteLine("Möchtest Du noch eine Aufgabe lösen (j/n)?")
    11. Loop Until ReadKey(True).Key = ConsoleKey.N ' (True) bewirkt, dass Zeichen nicht angezeigt wird
    12. WriteLine("Dann einen schönen {0} noch.", Now.ToString("dddd"))
    13. ReadKey()
    14. End Sub
    15. Sub Rechenautomat(Untergrenze As Double, Obergrenze As Double)
    16. Dim sEin As String ' Für die Eingabe des Benutzers
    17. Dim iEin As Double ' Die Eingabe nach Double gewandelt
    18. Dim iA, iB, iErg As Double ' Summanden der Aufgabe und Ergebnis
    19. Dim ZufallObj As New Random ' Objekt zum Erzeugen von Zufallszahlen
    20. ' Zufällige Summanden im Bereich 1-10 bestimmen
    21. iA = 1 + 11 * ZufallObj.NextDouble
    22. WriteLine(iA)
    23. iA = Math.Round(iA, 1)
    24. WriteLine(iA)
    25. iB = 1 + 11 * ZufallObj.NextDouble
    26. WriteLine(iB)
    27. iB = Math.Round(iB, 1)
    28. WriteLine(iB)
    29. iErg = iA + iB ' Ergebnis berechnen
    30. WriteLine(iErg)
    31. 'Console.Clear() ' Bildschirm löschen
    32. WriteLine(iErg)
    33. WriteLine("Bitte löse folgende Aufgabe!")
    34. Do
    35. Write("{0} + {1} = ", iA, iB) ' Aufgabe stellen
    36. sEin = ReadLine() ' Nicht vergessen, Readline liefert String
    37. ' Sichere Konvertierung von String nach Int32
    38. Try
    39. iEin = Convert.ToDouble(sEin)
    40. Catch ex As Exception
    41. WriteLine("Ich verstehe ihre Eingabe nicht.")
    42. WriteLine("Es wird jetzt mal die 0 angenommen")
    43. iEin = 0 ' Man hätte den Try-Catch-Teil auch wieder in eine Schleife ...
    44. End Try
    45. If iEin = iErg Then
    46. WriteLine("Super! Du hast die Aufgabe {0}+{1}={2} richtig gelöst.", iA, iB, iErg)
    47. Else
    48. WriteLine("Dein Ergebnis {0} ist leider falsch!", iEin)
    49. WriteLine("Bitte nochmals versuchen!")
    50. End If
    51. Loop Until iEin = iErg
    52. End Sub
    53. End Module
    Ganz am Schluss würde ich iEin auch runden.

    Weil die Eingabe enthält ja beliebig viele Nachkommastellen, die du beim Ergebnisse rausgekürzt hast
    ODER:
    Die Zahlen werden noch nicht gerundet addiert,aber die angezeigten Zahlen sind gerundet -- Rundungsfehler.
    Du musst das Programm mit den selben Zahlen rechnen lassen welche angezeigt werden.

    Mfg

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Kilian_98“ ()

    Ich hab gerade aus Spaß mal ein bisschen mit dem Ding rumgespielt :D..

    Hier haben wir dein genanntes Problem, oder^^?

    (Siehe Bild)
    Bilder
    • Unbenannt.PNG

      20,58 kB, 683×347, 189 mal angesehen
    Polling is trolling!

    Achtung: Ich habe die komische Angewohnheit, simple Dinge zu verkomplizieren..
    Das Problem sind Zahlen, die im Zehnersystem mit endlich vielen Kommastellen darstellbar sind, im Binärsystem aber unendlich viele nachKommastellen haben.
    glaub dezimal 0,1 ist im Binärsystem nicht exakt abzubilden.

    Plausibel kann ichs vlt. am 3-er Zahlensystem machen: 1/3 ist im 3-er-System schlicht 0,1.
    Im Dezimalsystem ists
    0,33333333333333333333333333333333333333333333333333333333333333333333333333333333
    und ist immer noch nicht genau.
    Drum erst runden, dann rechnen lassen, dann kommen PC und Benutzer aufs selbe Ergebniss

    Dann wird aus 1/3 wieder 0,3. :)

    Bsp.

    PC: 0,2 + 0,2 = 0,4 --> runden 0,5
    User: 0 + 0 = 0 --> runden 0

    PC <> User

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Kilian_98“ ()

    Parmaster schrieb:

    Rundungsproblem
    In diesem Falle solltest Du Dich ein wenig mit Epsilontik befassen. Du musst abtesten, ob das Ergebnis in einem gewissen Bereich liegt, und dieser Bereich muss einfach geeignet gewählt werden.
    Wenn Du mit einer Nachkommastelle rechnest, sollte das Epsilon etwa 0,1 groß sein, das musst Du aber ausprobieren.
    Beispiel:
    (1 / 3) + (1 / 3) + (1 / 3) = 1
    auf eine Nachkommastelle gerundet:
    0,3 + 0,3 + 0,3 = 0,9
    Oder
    Du beschneidest die Zufallszahlen sofort auf eine Nachkommastelle:

    VB.NET-Quellcode

    1. Dim NextDouble = Math.Round(ZufallObj.NextDouble * 10) / 10
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wa ich gerade erst gesehen habe:

    Im Bild von Rootbob sieht man, das dass Ergebnisse schon richtig errechnet wurde,
    gibt er aber dasselbe noch einmal ein, gibt es einen Fehler, ich würde also sagen,
    dass es doch kein Rundungsfehler ist.
    (Zumal ja erst gerundet wird, und dann berechnet, was ich vorher leider über sehen habe)

    Ich würde also die Konvertierung noch einmal anschauen, und die Eingabe und das Ergebnisse
    noch einmal in eine Zeile schreiben lassen (bei einem Fehler)
    Steht dort immer noch das gleiche, musst du dir die Abfragemethode noch einmal anschauen