Zu dumm zum Rechnen?



  • Hallo zusammen,

    also entweder ich bin zu dumm, oder C (gehe derzeit noch von mir aus)!

    Alles was ich möchte ist die Konkatenation dreier Dezimalzahlen, ohne sie in einen String zu verwandeln.

    Wie macht man das? => Man nimmt die erste, multipliziert sie mit 10^Anzahl Dezimalstellen der 2. Zahl^ + die 2. Zahl.
    Das Ergebnis daraus dann noch mal 10^Anzahl der Stellen der 3. Zahl^ + die 3. Zahl!

    Also:

    Zahl1 = 1234
    Zahl2 = 1234567890
    Zahl3 = 56789

    1. Schritt: Zahl1 * 1010 + Zahl2 = 12341234567890
    2. Schritt: Ergebnis aus Schritt1 * 105 + Zahl3 = 1234123456789056789

    Oder nicht?

    Nur dieser Code macht das nicht, liegt das an den Datentypen?

    unsigned long zahl1= 1234;
    long zahl2 = 1234567890;
    int zahl3 = 56789;
    
    double firstStep = pow(10, 10);
    double secndStep = pow(10, 5);
    
    double step1 = (zahl1* firstStep) + zahl2;
    double step2 = (step1 * secndStep) + zahl3;
    

    Bei den ersten beiden scheint alles zu klappen, nur nach Schritt3 bekomm ich immer falsche Werte!

    Gebe das Ganze wie folgt aus:

    fprintf(stderr, "firstStep: %f\n\n", firstStep);
    fprintf(stderr, "secndStep: %f\n\n", secndStep);
    fprintf(stderr, "Step1: %f\n\n", step1);
    fprintf(stderr, "Step2: %f\n\n", step2);
    

    Ausgabe:

    firstStep: 10000000000.000000
    secndStep: 100000.000000
    Step1: 12341234567890.000000
    Step2: 1234123456789056800.000000

    😕

    Was stimmt da noch nicht? Liegt das an den 3 verschiedenen Typen unsingned long, long, int?
    Irgendwie scheint die 3. Zahl "aufgerundet" zu werden, wenn man sich nach der 2. Dezimalstelle ein Komma vorstellt!?

    Interessanterweise liefert folgendes:

    fprintf(stderr, "(step1 * secndStep): %f\n\n", (step1 * secndStep));
    

    (step1 * secndStep): 1234123456788999900.000000 😕 😕 😕

    Selbst wenn ich alle 3 Ausgangszahlen als double-Typen nehme klappt es nicht!

    Ciao



  • Hallo

    Nö, liegt nicht an den Datentypen. Ergebnisse stimmen auch.

    firstStep: 10^10 = 10  000 000 000
    secndStep: 10^5  = 100 000
    Step1:     1234 * (10^10) + 1234567890 = 1.234123457 x 10 ^ 13
    Step2:     1234 * (10^10) + 1234567890 * 1.234123457 x 10 ^ 13 * 10 ^ 5 + 56789
                                           = 1.234123457 x 10 ^ 18
    

    Siehste, passt also.

    Mfg.
    way



  • Hm?

    Und wie erklär ich mir dann die Ausgaben, die ich bekomme?

    Die stimmen doch vorn und hinten nicht!

    V.a. die:

    (step1 * secndStep): 1234123456788999900.000000

    Wer rundet denn da?

    Der einfache Weg, das ganze via sprintf() in nen String zu konkatenieren geht natürlich!

    char resultString[20];
    snprintf(resultString, 20, "%u%u%u", 1234, 1234567890 , 56789);
    

    Aber die Umwandlung in nen String brauche ich an ner anderen Stelle, hier hätte ich das Ganze gern als Zahl gehabt!

    Scheint wohl nicht so zu gehen, wie ich mir das vorstelle!

    Ciao



  • double hat halt auch nur eine begrenzte Anzahl an signifikanten Stellen.

    http://de.wikipedia.org/wiki/IEEE_754



  • Ok, verstanden.

    Aber nach dem, was dort steht, müsste long double ja funktionieren, oder etwa nicht?

    Hatte damit allerdings auch kein Glück.

    Dann bleibt wohl nur die Darstellung als String?

    Ciao



  • Reth schrieb:

    Dann bleibt wohl nur die Darstellung als String?

    ^^dann kanste aber nicht mit rechnen. floats und doubles sind aber auch doof, wenn man nur ganze zahlen hat. nimm doch ne 'big number' library wie GMP oder sowas.
    🙂



  • Zum Glück muss ich nicht rechnen!

    Brauche den Wert später nur als Zeichenkette. Da ich aber den Umgang mit Strings in C nicht sehr gelungen finde, wollte ich soviel als möglich das Belegen und Freigeben von Speicher an unterschiedlichen Stellen vermeiden!

    Einem char * (oder anderen Zeigern) sieht man ja nicht an, ob dessen Speicherplatz mit malloc() o.ä. angelegt wurde, oder aber mittels fester Arraygröße!

    Da mein benötigter String aber eh eine maximale Länge von 30 Zeichen haben soll, werde ich die einfach fest belegen, auch wenn ich nur 20 oder so verwende!

    Ciao



  • Reth schrieb:

    Einem char * (oder anderen Zeigern) sieht man ja nicht an, ob dessen Speicherplatz mit malloc() o.ä. angelegt wurde, oder aber mittels fester Arraygröße!

    Das ist ja auch, während man ein solches Array benutzt, irrelevant. Derjenige, der den Speicher anfordert, muss dafür Sorge tragen, dass er auch wieder freigegeben wird. In der Zwischenzeit ist das ein ganz normales Array.

    Und wie du schon selbst gesagt hast, nimm einfach ein festes Array, wenn du die Größe sowieso weißt. Ein übermäßiger und unnötiger Gebrauch von malloc ist sowieso Quatsch. 🙂



  • So mach ichs auch gerad. Hatte nur das hehre Ansinnen keinen Speicher zu verschwenden (auch wenns nur ein paar Byte sind)!

    Jaja, was man sich nicht alles für nen Stress macht für solche Kleinigkeiten!

    Ciao


Log in to reply