Autor Beitrag
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Mo 28.05.12 20:57 
Hey @ll,

ich habe mich gerade gefragt wie im System die Zahlen gerundet werden. Das Ergebnis findet ihr im Anhang als Bild, der Code dazu:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "Rundungstest";
            Console.ForegroundColor = ConsoleColor.White;

            ulong x = 9999999999999999999, y = 5000000000000000000;
            Console.WriteLine("{0} / {1} = {2}\tMit ulong / ulong", x, y, x / y);
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Round(ulong, double)", x, y, Math.Round(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Floor(ulong, double)", x, y, Math.Floor(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Truncate(ulong, doub)", x, y, Math.Truncate(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit ulong / double\n\n", x, y, (x / (double)y));

            x = 999999999999999;
            y = 500000000000000;
            Console.WriteLine("{0} / {1} = {2}\tMit ulong / ulong", x, y, x / y);
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Round(ulong, double)", x, y, Math.Round(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Floor(ulong, double)", x, y, Math.Floor(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Truncate(ulong, double)", x, y, Math.Truncate(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit ulong / double\n\n", x, y, (x / (double)y));


            x = 99999999999999;
            y = 50000000000000;
            Console.WriteLine("{0} / {1} = {2}\tMit ulong / ulong", x, y, x / y);
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Round(ulong, double)", x, y, Math.Round(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Floor(ulong, double)", x, y, Math.Floor(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit Math.Truncate(ulong, double)", x, y, Math.Truncate(x / (double)y));
            Console.WriteLine("{0} / {1} = {2}\tMit ulong / double", x, y, (x / (double)y));
            Console.Read();
        }
    }
}


Kann mir das jemand erklären?
Einloggen, um Attachments anzusehen!
_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 28.05.12 21:42 
Wenn du nicht explizit rundest, wird offensichtlich der ganzzahlige Anteil als Ergebnis benutzt. Also das gleiche wie Truncate. Sprich die Nachkommastellen werden ignoriert.
interessierter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 75



BeitragVerfasst: Mo 28.05.12 21:42 
Hallo

Bin zwar Anfänger, aber vielleicht kann ich dir hier weiterhelfen :)

Dazu brauchst du Math.Round

Ich habe hier ein kleines Beispiel:
ausblenden C#-Quelltext
1:
2:
3:
double x = 2.34567//Zu rundender Wert x
x = Math.Round(x, 2); //2 steht für ''wieviele Stellen nach dem Komma runden''
Console.WriteLine(x);


Hoffe es ist das was du suschst. Sonst gibts hier sicher jemand der dir weiterhelfen kann.

Grüsse
interessierter

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 28.05.12 22:25 
Zitat:
Kann mir das jemand erklären?


Du kannst es einfach nachlesen. An jeder Stelle der Math Klasse deren Methode du ja schon benutzt steht es dran. Für Gleitkommatypen wird 'IEEE 754' benutzt.

Wenn dir ein bestimmtes Ergebnis deines Tests spanisch vorkommt solltest du gezielt nach diesem fragen. Ich und bestimmt sonst auch keiner hat Lust jeden Einzeltest durchzukauen.
C# Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Fr 01.06.12 13:11 
Ok Sorry für die ungenaue Beschreibung und Danke für die Antworten.
Worauf ich hinaus möchte ist dass Math.Floor(double) - welches ja die nächst kleinere Ganzzahl ausgibt - und Math.Truncate(double) anscheinend nicht so genau arbeitet wie die normale Division von ulong / double. Wenn ich diese 2 Typen fülle, bis die fast Höchstmögliche Ziffernzahl erreicht ist (siehe 1. Post Code-Zeile 15), erreiche ich bei ulong / ulong immer noch korrekter weise 1. Bei Truncate und bei Floor erhalte ich jetzt jedoch 2.
ausblenden C#-Quelltext
1:
2:
3:
4:
ulong x = 9999999999999999999, y = 5000000000000000000;
Math.Floor(x / (double)y) = 2
Math.Truncate(x / (double)y) = 2
x / y = 1

Wieso?

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 01.06.12 13:41 
Für Floor und Truncate nimmst du vorher ein Division mit doubles vor. Bei der anderen Division eine mit ulongs. x hat aber mehr signifikante Stellen als man in einem double darstellen kann und verliert deshalb bei dem cast an Genauigkeit (Faustwert ist das double ungefähr 15 signifikante Stellen hat). Caste mal x direkt nach double und sieh dir den Wert an bzw. lass Truncate und Floor weg und betrachte nur die reine Division mit doubles. Da wird ebenfalls 2 rauskommen.

ausblenden C#-Quelltext
1:
(double)x / (double)y					
C# Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Fr 01.06.12 14:11 
Achso Danke. Verliert double nur wegen der mögichen größe der Kommastellen seine Genauigkeit? ulong hat keine Kommastellen und ist deshalb exakt?

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 01.06.12 14:20 
Zitat:
Achso Danke. Verliert double nur wegen der mögichen größe der Kommastellen seine Genauigkeit?


Nein. Es geht um signifikante Stellen wo das Komma steht ist egal. 0,0 ..... hundert 0en ... 01 ist darstellbar genauso wie 1 ... hundert nullen ... 0,0 . Würden da jetzt aber nicht eine 1 stehen sondern eine Zahlenfolge unterscheidbar von 0 länger als 15 Ziffern wirst du, Prinzip bedingt, ungenau. Wenn du höhere Genauigkeit willst bei kleinerem Zahlenraum kannst du auf decimal anstatt double ausweichen.

Ansonsten am besten noch mal das Thema Gleitkommazahl zum Beispiel in Wikipedia nachlesen wo die prinzipiellen Problem liegen.