Diskuze: Jak otočit slovo?
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 25 zpráv z 25.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
label.Text = new string(textbox.Text.Reverse().ToArray());
Diky moc.. šlo by to napsat ve více kodech abych to pochopil?:)
To je součást frameworku, na tom se nedá moc co vysvětlovat
Vezmeš string, reverzneš ho, převedeš na pole, vytvoříš instanci.
Nauč se základní konstrukce programování, pak se nebudeš muset ptát.
Problém je, že ty jsi "nereverznul" string. Kdyby ano, nemusel bys výsledek pak převádět na pole. Ve skutečnosti jsi vytvořil enumerátor pro typ char, kterýs pak převedl na pole typu char a to pak vložil do konstruktoru stringu.
Rozepsaně je to takto, snad to pomůže michaelbeats7
string retezec = "Test pro převrácení.";
IEnumerable<char> enumerator = retezec.Reverse();
char[] pole = enumerator.ToArray();
string prevracenyretezec = new string(pole);
Console.WriteLine(prevracenyretezec);
Hoši, co kdybyste mu to ukázali i s tím cyklem? Ano lze to krásně napsat na jeden řádek, ale v rámci algoritmizace je možná dobré si to aspoň zkusit. Navíc nezapomeňte, že metoda Reverse je taky napsaná v C#, přemýšleli jste nad tím, jak funguje?
string input = "Pes";
string output = ""; // vytvoříme si proměnnou kam budeme řpidávat písmena
// obrácený cykl, i bude nejprve 2, pak 1, 0 a u -1 už podmínka neprojde
for (int i = input.Length - 1; i >= 0; i--) {
output += input[i]; // přilepíme aktuální procházené písmeno do výsledku
}
Console.WriteLine(output);
Ve skutečnosti se udělalo interně tohle:
string text = "Pes";
char[] pole = text.ToCharArray();
Array.Reverse(pole, 0, pole.Length);
string novyText = new string(pole);
A to se zase dá převést ještě o úroveň níže:
string text = "Pes";
char[] pole = text.ToCharArray();
int i = 0, j = pole.Length - 1;
while (i < j)
{
char tmp = pole[i];
pole[i] = pole[j];
pole[j] = tmp;
i++;
j--;
}
string novyText = new string(pole);
To si nemyslím. Nebudu se tvářit jako velký expert na C# a potažmo LINQ, ale takto to nefunguje. Tak, jak jsi to napsal, jsi vynechal to podstatné, totiž líné vyhodnocení "deferred execution" metody Reverse, ostatně víc je tady včetně reimpletace metody:
Jo, já se koukal na reverse u listu.
Deferred execution v tomto případě nemá žádnou roli jinak jo, ta implementace v tom
linku je celkem přesná.
Každopádně jsem si napsal malý benchmark, kódy seřazeny od nejrychlejšího:
1. Samostatně naimplementovaný reverse
string text = "as5d4as6d5";
char[] pole = text.ToCharArray();
int i = 0, j = pole.Length - 1;
while (i < j)
{
char tmp = pole[i];
pole[i] = pole[j];
pole[j] = tmp;
i++;
j--;
}
string novyText = new string(pole);
2. Pomocí reverse metody na Array třídě
string text = "as5d4as6d5";
var arr = text.ToCharArray();
Array.Reverse(arr);
string novyText = new string(arr);
3. Pomocí reverse metody na List<T>
string text = "as5d4as6d5";
var tmp = text.ToCharArray().ToList();
tmp.Reverse();
string novyText = new string(tmp.ToArray());
4. pomocí reverse metody na IEnumerable<T>
string text = "as5d4as6d5";
string novyText = new string(text.Reverse().ToArray());
Pozn. ta 3 a 4 se dost blbě měří, jednou vyjde poměr časů 1:10 a potom
zase 10:1
Souhlasím, že v tomto konkrétním případě to význam nemá, když uvážím, že enumerátor napřed musí udělat pole a pak teprve nový string. Ale to záleží, jak je to v c# naimplementované.
Ten benchmark jsi podle mne nenapsal vhodně. Abys to lépe porovnal, měl bys zkusit obracet extrémně dlouhé řetězce. Na řetězce, co má 10 znaků nic nezměříš. Jestli se ti chce, zkus dosadit do svého benchmarku toto s hodnotou end povězme třeba 20 000.
public static string CreateString(int end)
{
var r = new Random();
string newstr = "";
for (int i = 0; i < end; i++)
{
newstr += Char.ConvertFromUtf32(r.Next(65, 122));
}
return newstr;
}
V podstatě stejné výsledky, ale Array.Reverse tam volá interně něco rychlejšího pro zpřeházení paměti, takže je to o pár % rychlejší.
Tam je stejné. U toho listu se volá interně Array.Reverse, tak je to pomalejší jen o tu konverzi na list.
Škoda, že jsi nenapsal ty časy. Pochopil jsem to správně, že ten první byl cca 10x rychlejší než ten poslední? Asi sis nevšiml, jak to škáluje?
Pánové, vy jste se nikdy nezabývali profilingem kritických sekcí
aplikace, že?
Schválně, za předpokladu, že kód je v C a optimalizace nezasáhne do instrukčního toku (což obvykle udělá), který kód bude rychlejší?
double sum = 0;
for (int i = 0; i < n; i++)
sum = sum + array[i];
nebo
double sum = 0;
for (int i = 0; i < n; i++)
sum = array[i] + sum;
To by mě zajímalo, spíš teda - bude v tom rozdíl?
myslím, že v tom případě minimální, větší rozdíl by byl, kdyby první ukázka byla správně napsaná
double sum = 0;
for (int i = 0; i < n; i++)
sum += array[i];
Podľa mňa bude druhá verzia o niečo rýchlejšia ako tá prvá, mám pravdu?
sum += array[i];
je identické s
sum = sum + array[i];
je to iba skrátený zápis, ale oba výrazy sú preložené prekladačom rovnako.
A můžeš to něčím podložit? Vzhledem k tomu, že se tvoje varianta nutně musí přeložit do jedné ze dvou nabízených verzí, to nedává moc smysl.
Zajímavé,
nakonec jsem si zkusil napsat vlastní benchmark a výsledek je trochu jiný.
Hlavně co se týče rychlosti s pomocí while cyklu (jméno: iterace). Tobě
vyšel jako nejrychlejší, pokud se nepletu, zatímco mně jako druhý
nejpomalejší. I když ty rozdíly mezi nejrychlejšími třemi jsou poměrně
malé.
Length of tested sentence is: 20000 chars.
Number of repetion is: 10000
Starting to evaluate...
[Enumerace, 00:00:11.0784580]
[Iterace, 00:00:00.7929593]
[ListMethod, 00:00:00.4238042]
[CharArray, 00:00:00.2655176]
Pokud by se chtěl někdo podívat, ten benchmark je tady:
Použití je jednoduché
var benchmark = new Benchmark(delka_retezce, pocet_opakovani_funkce_za_sebou);
benchmark.PrintResults();
Zobrazeno 25 zpráv z 25.