Diskuze: Pomozte udělat program
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Neregistrovaný

Zobrazeno 50 zpráv z 73.
//= 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.
Takhle to nepůjde, budeš se muset taky trochu snažit Nejprve se zamysli nad tím, jak
bys ty úlohy dělal jako člověk, my ti pomůžeme na to napsat program.
Jo zkoušel jsem, první dva mi fungují, ale myslím, že je nemám zcela
správně
tady je ten obvod a obsah kružnice:
double cisloPI = Math.PI;
Console.Write("Zadej poloměr kružnice : ");
string polomer = Console.ReadLine();
double polomer1h1 = Convert.ToDouble(polomer);
Console.Write("Obvod kruhu je: ");
Console.WriteLine(2 * cisloPI * polomer1h1);
Console.Write("Obsah kruhu je: ");
Console.Write(cisloPI * polomer1h1 * polomer1h1);
a tady ten válec:
Console.WriteLine("Toto je program pro výpočet objemu a povrchu válce:");
double polomerV, vyskaV, valecV, valecS;
Console.Write("Zadejte poloměr válce: ");
polomerV = Convert.ToDouble(Console.ReadLine());
Console.Write("Zadejte výšku válce: ");
vyskaV = Convert.ToDouble(Console.ReadLine());
valecV = Math.PI * Math.Pow(polomerV, 2) * vyskaV;
valecS = 2 * Math.PI * polomerV * vyskaV;
Console.WriteLine("Objem válce je: " + valecV);
Console.WriteLine("Povrch válce je: " + valecS);
Console.ReadKey();
Ale víc jsem bohužel už nevyplodil vůbec netuším jak ty ostatní
řešit
Třetí příklad asi zcela nechápu co má dělat. A co se týče čtvrtého, koukni se na tutoriály - cykly,pole apod. Jinak tenhle kod, jak jsem rychl přelít, správně ale pár rad
int=Convert.ToInt32(Console.ReadLine())
ti uloží hodnotu z klávesnice, tedy nemusíš dělat zvlášť string a
poté jej konvertovat, jenom taková rada . A amatér ? Vůbec ne
. Stač íse tomu věnovat a
přijdeš na to
Člověk může být současně amatérem (dělat to rád) i profesionálem (dělat to za peníze). Pokud to Amatérr nedělá rád, není amatérem.
K zadávání zdrojových kódů prosím používej ikonku "Vložení zdrojového kódu", takhle se to čte opravdu hrozně. Nebudu komentovat úpravu kódu, ale první vypadá dobře. U druhého máš v povrchu jen plášť, je třeba ještě přičíst 2x obsah podstavy. To jistě hravě opravíš, nezkoušel jsem to, ale připadá mi, že to vypadá docela dobře. Místo convert se používá parse, když načítáš číslo z textové podoby, viz můj příklad dále, ale nikdo ti za to v úkolu asi nevyhubuje.
Pomohu ti s těmi dalšími.
Zadat trojciferné číslo, vypsat počet 100,10,1
Mělo by stačit načíst normální string z konzole a převést ho na int.
Když bude větší než 999 a menší než 100, můžeš uživateli vyhuboat,
že není trojciferné, ale to není přímo v zadání. Každopádně zadané
číslo stačí přeci jen vydělit 100 a máš kolik v něm je stovek, vydělit
10 a máš desítky, jednotek tam je tolik, kolik je hodnota toho čísla Malý hint:
int cislo = int.Parse(Console.ReadLine());
Console.WriteLine("Stovek: {0}", cislo / 100);
Pokud dělíš 2 integery, dělení bude celočíselné, což ty potřebuješ.
Přečíst trojciferné číslo a vypsat ho pozpátku
Nevím, co se myslí tím přečíst. Číslo si zadáš jako string a poté ho převrátíš. Jde to udělat for cyklem, ale i velmi jednoduše. String si převedeš na pole znaků. Pole má metodu Reverse, ta ho otočí. Z pole poté uděláš zpátky string:
char[] arr = s.ToCharArray();
Array.Reverse(arr);
Console.Write(new string(arr));
Kdyby ti to přišlo moc složité, můžeš to udělat tím cyklem, projedeš zadaný text a po písmenkách vypíšeš pozpátku
Console.WriteLine("Zadej číslo:");
string s = Console.ReadLine();
for (int i = s.Length - 1; i >= 0; i--)
{
Console.Write(s[i]);
}
Ještě mi došlo že u 3. příkladu to u desítek nepůjde tak jednoduše. Můžeš od toho čísla odečíst 100 x (cislo / 100) a zbyde ti kolik tam je desítek a jednotek. Výsledek vydělíš deseti. Nebo by to šlo i přes to modulo.
Lepší by asi bylo použít obrácené Hornerovo schéma, ale výsledek by se musel před vypsáním obrátit.
Chci se zeptat proč je lepší používat Parse než Convert ?
Parse je o chlup rychlejší a kvalitněji zpracuje vadný vstupní řetězec. Convert vrátí 0 a o víc se nestará.
Děkuji všem za rady snad to nějak splácám , Jinak ano je to úkol do
školy učíme se programovat teprve chvíli ale od učitele jsem to prostě
nepochopil a to nejsem sám
Jo a ještě se vrátím k výpočtu přepony prav. trojúhelníka jak to bude z
mocninami?
Math.Pow(3, 2); // tři na druhou
Math.Pow(9, 1/2); //odmocnina z devíti
Místo druhé mocniny je často výhodnější použít násobení a místo
uvedené druhé odmocniny metodu Math.Sqrt()
.
Tak to určitě v tomto případě je, ale kdyby něco bylo x10 nebo třetí odmocnina, tak je pro mě pohodlnější používat Math.Pow().
Jemu nejde o pohodlnost, ale o zátěž... Tedy jako je to s internetem - nejrychlejší cesta nebývá ta nejkratší.
Nevím jak je tomu v c# ale v Javě jsou všechny metody v Math nativní, tj. že se to nepočítá v JVM ale v Cečku bo C++ (nejsem si teď jistý který z těch dvou to je, ale myslím že Céčko), takže je to podstatně rychlejší než kdybych vypisoval třeba ** a * a * a * a * a * a * a * a * a * a **.
Díky něco jsem splácal akorát teď nevím jak dál viz.níže
Console.Write("Zadej stranu A: ");
int zKlavesnice = Convert.ToInt32(Console.ReadLine());
Console.Write("Zadej stranu B: ");
int zKlavesnice2 = Convert.ToInt32(Console.ReadLine());
Console.Write("Přepona je: ");
Console.Write(Math.Pow(zKlavesnice, 2) + Math.Pow(zKlavesnice2, 2));
Console.ReadKey();
Podle pythagorovi věty ti to tuším chybí akorát odmocnit:
Math.sqrt(Math.Pow(zKlavesnice, 2) + Math.Pow(zKlavesnice2, 2))
V manuálu C# je doporučeno Math.Pow()
používat jen pro
obecné umocňování kvůli horšímu výkonu. Pokud se Pythagorova věta
používá velmi často (např. při určování vzdálenosti ve 2D či 3D),
doporučuje se použít násobení a odmocňování. Výraz by pak vypadal
takto:
Math.Sqrt(zKlavesnice*zKlavesnice + zKlavesnice2*zKlavesnice2)
Nedalo mi to a musel jsem si to v Javě vyzkoušet, obdržel jsem celkem
nemilé výsledky, metoda pow() je asi 100x pomalejší. Po tomhle jsem usoudil
že některé metody v Math asi nebudou nejlépe přizpůsobené na výkon a
nativní metody budou nejlepší asi na dlouhé rozsáhlé výpočty a pro
komunikaci přímo se systémem.
Jinak kód na kterém jsem to zkoušel:
public static void main(String[]args){
double a;
double b;
long start;
long end;
start = System.nanoTime();
a = 5*5;
end = System.nanoTime();
System.out.println(end-start);
start = System.nanoTime();
b = Math.pow(5, 2);
end = System.nanoTime();
System.out.println(end-start);
}
No a jelikož je C# kopií Javy tak předpokládám že zde to bude stejné nebo aspoň podobné.
Takové měření je velmi nespolehlivé, měl bys to spočítat v nějakém cyklu třeba 1000x a pak z hodnot udělat průměr. Jelikož Java je VM, chovají s enějaké funkce při prvním volání jinak, než po volání opětovném. Tím nevylučuji tvůj výsledek, dost možná to vyjde stejně, ale v budoucnu bys mohl tímto způsobem dojít zcela jistě ke špatnému výsledku.
Hodil jsem to do cyklu 1 000x, a poté ještě do 10 000x opakovaném cyklu a metoda pow() byla pokaždé s relativně malou odchylkou 10x pomalejší. Když jsem to meřil pouze jednou vznikaly velké odchylky. Jinak díky za poznámku, nějak mi nedošlo že ve VM je první načtení je nejdelší.
Tomu bych vůbec nevěřil, protože kompilátor běžně nahrazuje výraz '5*5' výrazem 25 už v preprocesoru. Raději to dej jako parametr funkci a jak naznačil David Hartinger, nechej to uvnitř projet cyklem alespoň 1000×.
Dobře, tak se vracím ke svému starému a správnému tvrzení, že metody
nativní jsou nejrychlejší
Podle mého finálního měření jsou nativní metody 3x rychlejší.
Kód:
public class Test {
public static void main(String[]args){
double cislo;
double cislo2;
long []a = new long[1000];
long []b = new long[1000];
long start;
long end;
for(int i=0;i<1000;i++){
start = System.nanoTime();
cislo = naDruhou(5);
end = System.nanoTime();
a[i] = end-start;
}
for(int i=0;i<1000;i++){
start = System.nanoTime();
cislo2 = Math.pow(5, 2);
end = System.nanoTime();
b[i] = end-start;
}
System.out.println(secti(a)/1000);
System.out.println(secti(b)/1000);
}
private static double naDruhou(double cislo){
return cislo*cislo;
}
private static long secti(long[]pole){
long soucet=0;
for(int i =0;i<pole.length;i++){
soucet+=pole[i];
}
return soucet;
}
}
Zase to měříš divně. Cyklus musí být uvnitř funkce a měření času mimo cyklus. Měříš to i s časem volání funkce.
Mně teď vyšlo, že násobení je 10× rychlejší i při umocňování na desátou. Ovšem většinou se umocňuje jen na druhou, vyšší mocniny bývají výjimečné.
Kdybych dal měření uvnitř funkce tak násobení bude rychlejší o něco, protože do nativní metody měření nedám, takže u mocnění by se měřilo volání a u násobení ne a tím pádem násobení by mělo úlevy.
Však při běžném násobení ty úlevy má. Použij to ve stejném režimu, v jakém se to obvykle používá. Ta funkce je potřebná jen kvůli vyloučení optimalizace preprocesorem, aby k tomu násobení skutečně došlo. Klidně do té jedné funkce dej oba způsoby.
I po úlevách je nativní metoda několikrát rychlejší.
Kód:
package org.fugiczek.f_walk;
public class Test {
public static void main(String[]args){
double cislo;
long []a = new long[1000];
long []b = new long[1000];
long start;
long end;
for(int i=0;i<1000;i++){
a[i] = naDruhou(5);
}
for(int i=0;i<1000;i++){
start = System.nanoTime();
cislo = Math.pow(5, 2);
end = System.nanoTime();
b[i] = end-start;
}
System.out.println("Násobení: " + secti(a)/1000);
System.out.println("Mocnění: " + secti(b)/1000);
}
private static long naDruhou(double cislo){
long start, end;
double vysledek;
start = System.nanoTime();
vysledek = cislo*cislo;
end = System.nanoTime();
return end-start;
}
private static long secti(long[]pole){
long soucet=0;
for(int i =0;i<pole.length;i++){
soucet+=pole[i];
}
return soucet;
}
}
Zajímavé. Když jsem si zkopíroval tvůj kód, násobení mi vyšlo 2× rychlejší.
Nejspíš záleží na více faktorech, napadá mě že možná na různých OS volání nativní metody trvá odlišnou dobu.
Můžeme mít odlišnou verzi JRE. Mám 1.6.0_22. Také moc nevěřím nanosekundovému měření času, protože mezitím může dojít ke spoustě asynchronních událostí, které měření zkreslí.
JVM je prý optimalizovaný pro unixové operační systémy, mohou zde být velké rozdíly.
No odlišnou verzi máme určitě, já používám nejnovější buildy z JDK 8. Navíc mezi JRE 6 a JRE 7 jsou celkem podstatné změny. Probíhaly změny i ve JVM. Doporučil bych udělat alespoň upgrade na JRE 7 update 9 (poslední stabilní verze), JRE 6 má celkem dost bezpečnostních děr.
Je to možné. Také je možné, že bych po dvou letech a půl mohl konečně upgradovat svůj OS, ve kterém bude i nová verze JVM. Pořád váhám, který systém vybrat. Je to dost stará mašina s 1 GB RAM.
Javu skoro nepoužívám. Upgrade jednotlivých aplikací dělám jen při upgrade OS. Až na výjimky, do kterých JVM nespadá. Dělám jen pravidelné updaty systému, se kterými se updatují i ty aplikace.
Ještě jeden menší dotaz ohledně převrácení čísla jde to udělat ještě jinak než těmi dvěma způsoby?
char[] arr = s.ToCharArray();
Array.Reverse(arr);
Console.Write(new string(arr));
onsole.WriteLine("Zadej číslo:");
string s = Console.ReadLine();
for (int i = s.Length - 1; i >= 0; i--)
{
Console.Write(s[i]);
}
int puvodni=1234, prevracene=0, tmp=0;
while(puvodni>0){
tmp = puvodni%10;
prevracene = prevracene*10+tmp;
puvodni = puvodni/10;
}
Na konci cyklu bude v proměnné puvodni 4321
Jednoduchý program na výpočet povrchu a objemu válce bych udělal asi takto:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Výpočet_Obsahu_A_Povrchu_Válce
{
class Program
{
static void Main(string[] args)
{
start:
double vyska;
Console.WriteLine("Program Na Vypočítání Povrchu A Objemu Válce");
Jedna:
Console.WriteLine("Zadejte Prosím Výšku Válce");
vyska = double.Parse(Console.ReadLine());
if (vyska <= 0)
{
Console.WriteLine("Zadána Chybná hodnota: {0}", vyska);
goto Jedna;
}
else
{
double polomer;
Dva:
Console.WriteLine("Nyní Prosím Zadejte Poloměr Válce");
polomer = double.Parse(Console.ReadLine());
if (polomer <= 0)
{
Console.WriteLine("Zadána Chybná Hodnota: {0}", polomer);
goto Dva;
}
else
{
double povrch;
povrch =
(3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812
* 2) * polomer * (polomer + vyska);
double obsah;
obsah =
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812
* (polomer * polomer) * vyska;
Console.WriteLine("Polomer = {0}", polomer);
Console.WriteLine("Výška = {0}", vyska);
Console.WriteLine("Obsah Válce : {0}", obsah);
Console.WriteLine("Povrch Pláště Válce: {0}", povrch);
Console.WriteLine("Pokud chcete znovu vypočítat povrch a objem válce
zadejte číslo 666 pokud nechcete zadejte jiné číslo");
double i;
i = double.Parse(Console.ReadLine());
if (i == 666)
{
goto start;
}
else
{
goto konec;
}
}
}
konec:
Console.WriteLine("Konec Programu");
}
}
}
Ehm, par poznamek
Ano, C++ i C# mají goto, java ma myslim nejakou obdobu se slovickem break.
Jsou extrémní případy, kdy je řešení s goto efektivnější a přehlednější než bez, ale to jsou vyjímky (pochopil bych to třeba když máte v sobě zanořené 4 cykly a chcete z nich hned vyskočit těsně za ně) a i překladače kód s goto většinou nedokážou tak dobře optimalizovat.
Goto mi s prominutím přijde jako největší prasárna. Nejen že to dělá občas neplechu, ale prostě se to nepoužívá, nebo jsem neviděl u nikoho v C# použít goto
Ano, je to prasárna, ale jsou situace, kdy je to elegantnější než cokoliv jiného, i když jsou tak řídké, že se to skoro nepoužívá.
Ty řídké situace vznikají nesprávným rozborem problému. Od doby, kdy existují klíčová slova break, continue, return a throw, není goto vůbec potřebné. Obešel jsem se bez něj i v době, kdy tato klíčová slova nebyla k dispozici.
Používání goto pro posunutí v kódu směrem dopředu (dolů) je prasárna asi vždycky, já to používam občas když sem zahrabanej v nějakých podmínkách nebo cyklech a potřebuju se tam odsud dostat někam zpátky, většinou na začátek funkce. Většinou to používam jenom v main, když v nějakých výjimečných situacích potřebuju aby program začal od znova. Přijde mi to přehnednější než to dělat rekurzí, nebo nějakym velkym cyklem.
Tak takovou situaci si vůbec nedovedu představit. Nevidím důvod, proč bych se měl vracet na začátek funkce.
Některé jazyky goto vůbec nemají. Jiné neumožňují ani přepsat hodnotu proměnné a přesto se v nich dá napsat vše.
Samozřejmě se místo goto dá snad všude použít některá z variant break, continue, return a vyjímky, ale pokud jde někde třeba o rychlost, tak goto může přispět ke značné optimalizaci.
A opravdu jsou situace, kdy je i goto přehlednější, než výše zmiňovaná klíčová slova, ale je to opravdu velmi zřídka.
EDIT: A jeho používání jinak taky považuji za prasárnu, ale prostě jsou místa, kde i goto má své opodstatnění.
Zobrazeno 50 zpráv z 73.