IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

Sčítanie ľubovoľne veľkých čísel v C # .NET

Napadlo vás niekedy, ako by sa sčítavali číslo väčšie ako dátové typy? Trebárs takých 80 miliárd alebo ešte viac? V tomto prípade môžeme použiť dátovú štruktúru BIGINT, ktorý reprezentuje nekonečne veľké číslo.

My si za účelom precvičovanie skúsime použiť metódu LSS na ukladanie čísel ako jednotlivé cifry. Túto metódu v praxi nepoužívajte, je len precvičenie programovanie a myslenia.

Veľké prirodzené číslo budeme v programe reprezentovať ako zoznam. Napr .: 879653 by v zozname vyzeralo takto: 8; 7; 9; 6; 5; 3

V tutoriále si nielen precvičíme používanie Listu <>, cyklov a parsovanie, ale tiež StreamReader a to preto, že program bude načítať čísla z textového súboru. Tak sa poriadne pripútajte a ideme na to!

Najskôr musíme pridať menný priestor pre prácu so súbormi System.IO. IO znamená Input-Output. Náš kód by mal vyzerať nejako takto:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

Vďaka tomuto riadku budeme môcť používať napríklad StreamReader pre načítanie textových súborov alebo napríklad StreamWriter pre ich zápis.

Aby kód vyzeral prehľadnejšie, vytvoríme metódu pre načítanie čísel zo súboru a druhú metódu pre sčítaní čísel a následný výpis. V metóde Main iba zavoláme tieto metódy.

1) Príprava

Než začneme, deklarujeme si nejaké premenné mimo metódu Main, aby sa nachádzali v triednom odbore platnosti

static List<int> cislo1 = new List<int>();
static List<int> cislo2 = new List<int>();
static List<int> vysledek = new List<int>();

List je vlastne dynamické pole (počet jeho prvkov nie je pevný) a keďže nevieme o aké veľké číslo pôjde, je to asi najjednoduchšie voľba.

Ďalej si vytvoríme v počítači obyčajný textový súbor a napíšeme do neho dve čísla, každé na iný riadok.

2) Načítanie zo súboru

Vytvoríme si statickú metódu načíta (), ktorá nemá žiadny parameter.

static void Nacti()
{

}

Vnútri metódy vytvoríme blok pre prácu so súbormi:

using(StreamReader sr = new Streamreader(***));
{
}

Using označuje vnorený blok v ktorom používame StreamReader. Medzi jeho zloženými zátvorkami je kód, v ktorom načítame súbory. Po ukončení kódu medzi zátvorkami sa StreamReader ukončí.

*** - cesta k súboru s textom, napr .: @ "C: \ temp \ text.txt"

Zavináč nám vo stringu "vypína" escape sekvencie. Ak by sme ho nechceli použiť, museli by sme miesto každého \ napísať \\.

Do bloku using vložíme nasledujúci kód, ktorý si hneď vysvetlíme:

//Pomocná proměnná
int c;
//Cyklus načítá do cislo1 dokud nenarazí na konec řádku nebo souboru
while ((c = sr.Read()) != 13 && c != -1)
{
    //Převod na hodnotu (ne ASCII)
    c = (int)Char.GetNumericValue((char)c);
    //Přidání do seznamu
    cislo1.Add(c);

}
//Přeskočení hodnoty 10
sr.Read();

//Cyklus totožný s prvním, ale načítá do cislo2
while ((c = sr.Read()) != 13 && c != -1)
{

    c = (int)Char.GetNumericValue((char)c);

    cislo2.Add(c);

}

c je pomocná premenná, do ktorej zapisujeme hodnotu prečítaného znaku (hodnoty sú z ASCII tabuľky).

Nasleduje cyklus while, ktorý prebieha tak dlho, ako platí podmienka.

Do c priradíme znak, potom sa opýtame, či sa c nerovná 13 (na konci riadku sú vždy 2 netlačiteľné znaky a to: 13 10) alebo -1 (sr.Read () vracia -1 ak sa dostane na koniec súboru).

Teraz nám však nastáva problém. Premenná c je celé číslo a my celé číslo potrebujeme, ale toto celé číslo neukazuje hodnotu, ale číslo znaku v tabuľke ASCII.

Preto musíme na premennú c Přetypování na char použiť metódu Char.GetNumeric­Value (), ktorý nám vráti hodnotu čísla a tú až potom pretypovať na int. Viem, že to pre niekoho môže znieť zložito, ale ak sa nad tým zamyslíte, vezmete si papier a ceruzku a načrtneme si to, uvidíte, že je to veľmi jednoduché.

A teraz nám už len zostáva zapísať číslo do zoznamu.

Po prebehnutí prvého cyklu je celé číslo zapísané v zozname znak po znaku a cyklus narazí na číslo 13 (čo je znak konca riadku), ktoré nezapíše a ukončí sa.

sr.Read (); nám prečíta ďalší znak a to 10, ktorú chceme iba preskočiť a tak ju nikam nezapisujú.

Nakoniec ešte opakujeme rovnaký cyklus, jenom zapisujeme číslo2.

3) Sčítanie

Vytvoríme si statickú metódu Sect ():

static void Secti()
{
    //Rozdíl v počtu prvků jednotlivých polí
    int rozdil = Math.Abs(cislo1.Count - cislo2.Count);

    //Přidávání 0 na začátek
    if (cislo1.Count > cislo2.Count)
    {
        for (int j = 0; j < rozdil; j++)
        {
            cislo2.Insert(0, 0);
        }
    }
    //Přidávání 0 na začátek
    else if (cislo2.Count > cislo1.Count)
    {
        for (int j = 0; j < rozdil; j++)
        {
            cislo1.Insert(0, 0);

        }
    }

    //Zápis do stringů (jenom kvůli výpisu)
    string c1 = string.Join("", cislo1);
    string c2 = string.Join("", cislo2);

    //Výpis
    Console.WriteLine("{0,60}",c1.TrimStart('0'));

    Console.WriteLine("{0,60}",c2.TrimStart('0'));


    for (int i = 0; i < 65; i++)
        Console.Write("=");




    //Výpočet výsledku
    int zbytek = 0;
    List<int> vysledek = new List<int>();

    //cyklus sčítající jednotlivé prvky a přičítající zbytek
    for (int i = 1; i <= cislo1.Count; i++)
    {
        //Sečte čísla nad sebou a přidá zbytek
        int cislo = cislo1[cislo1.Count - i] + cislo2[cislo2.Count - i] + zbytek;
        //Zbytek je vynulován
        zbytek = 0;

        //Při sčítání dvou jednociferných čísel nemůžeme dostat číslo větší než 18,
        //proto nemusíme řešit zbytek větší než 1
        if (cislo >= 10)
        {
            zbytek = 1;
            cislo -= 10;
        }
        //Vložení čísla na začátek seznamu
        vysledek.Insert(0, cislo);

    }
    //Pokud při posledním číslu by byl zbytek, napíše ho jako první
    if (zbytek != 0)
    {
        vysledek.Insert(0, zbytek);
    }

    //Výpis výsledku
    string vys = string.Join("", vysledek);
    Console.WriteLine("\n{0,60}",vys);

}

Vytvoríme si premennú rozdil, do ktorej zapíšeme absolútnu hodnotu rozdielu počtu prvkov v oboch číslach.

Napr. 125 - 3 cifry, 22568 - 5 cifier, rozdiel = | 3-5 | = 2

Urobili sme to preto, aby sme vedeli koľko 0 pred ktoré číslo prirobiť. Chceme obidva zoznamy rovnako dlhé, aby sme ich prechádzali jedným jednoduchým cyklom.

Nasledujú 2 podmienky pre zistenie kratšieho zoznamu a doplnenie 0 na jeho začiatok.

Následne vytvoríme dve premenné typu string a zapíšeme do nich zoznam pomocou metódy string.Join (), oddeľovač nastavíme na prázdny znak, pretože chceme číslo v jednom kuse.

Reťazce vypíšeme zarovnané na 60 miest (kvôli veľkým číslam)

Potom napíšeme veľké množstvo "=" pre vytvorenie deliace čiary na obrazovke.

Nasleduje asi nejzáživnější časť a tou je výpočet. Vytvoríme si premennú pre zapisovanie zvyšku a nový zoznam pre výsledok.

Postup počítania je dostatočne popísaný v kóde a tak zrovna preskočíme do metódy Main (), čím sa chýlíme ku koncu.

V metóde Main jenom jednoducho zavoláme metódy a potom použijeme Console.ReadLine (), nech sa nám program sám neukončí.

static void Main(string[] args)
{

    Nacti();
    Secti();
    Console.ReadLine();
}

Teraz stačí len spustiť a uvidíte, ako ste túto lekciu zvládli :)

Ak by boli nejaké otázky, napíšte do komentárov alebo správu.

PS. Pre precvičenie si môžete program skúsiť prepísať pre načítanie čísel zo vstupu alebo napríklad vytvoriť násobenie.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 108x (33.88 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Všetky články v sekcii
Zdrojákoviště C # .NET - Kolekcia a LINQ
Článok pre vás napísal konecnyj96
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje programování v C# a C++. Občas si také pohraje s Unity nebo Blenderem
Aktivity