reklama
Aktuality  |  Články  |  Recenze
Doporučení  |  Diskuze
Grafické karty a hry  |  Procesory
Storage a RAM
Monitory  |  Ostatní
Akumulátory, EV
Robotika, AI
Průzkum vesmíru
Digimanie  |  TV Freak  |  Svět mobilně

Pomoc s programem

Satoshi (3)|29.12.2010 11:55
Dobrý den, chtěl bych se zeptat, jestli by nebyl něco schopen mi poradit, co je špatného na tomto programu:
Je to dělané ve Visual Studiu 2008 Express.
Program je na principu toho, že když uživatel zadá úhel, program jej přepočítá na radiány a následně vypočítá sin 2*úhel a 2 * sin úhlu * cos úhlu, aby se dokázala rovnost. Tohle funguje, ale problém je, pokud zadá uživatel hodnotu 90 a vyšší.

namespace Uhel
{
public partial class Vzorce : Form
{
public Vzorce()
{
InitializeComponent();
}

private void Alfa_TextChanged(object sender, EventArgs e)
{

try
{
double Fi = Convert.ToDouble(Alfa.Text);
double Alpha = (Math.PI / 180) * Fi;
double x = 2 * (Math.Sin(Alpha)) * (Math.Cos(Alpha));
double y = Math.Sin(2 * Alpha);

sinus2alfa.Text = Convert.ToString(x);
sina_sina_cosa.Text = Convert.ToString(y);

}
catch
{

MessageBox.Show("Zadejte číslo!");
}
}
Pabler (425)|29.12.2010 13:35
same prve pozor pri prevode zo stupnov na radiany, mas tam celociselne delenie !

double Alpha = (Math.PI / 180) * Fi;
prepis na:
double Alpha = (Math.PI / 180.0) * Fi;
alebo
double Alpha = (Math.PI / (double)180) * Fi;
Satoshi (3)|29.12.2010 16:04
Díky za odpověď. Přesto jeden problém přetrvává... program už počítá všechny úhly kromě násobků 90.
Tak nwm, jestli se vyplatí ještě hledat chybu, nebo bude lepší zavést to, že pokud uživatel zadá násobek 90, tak se to přesměruje na 0. Pokud ano, tak bych se chtěl zeptat, jak by se to tady dalo.
Pabler (425)|30.12.2010 01:43
nuz dalo by sa to zhadzovat nasledovne:
if (Fi % 90 == 0) Fi = 0; //hned po nacitani z textboxu ....
//prepis: ak je zvysok po celociselnom deleni 0, tak nastav uhol 0

No skusil som rozbehnut tvoj kod, a zda sa, ze funguje normalne ....
pre uhol 90° by to malo dat 0
....
tak si pozri co sa cca deje:
prejde to cez par prepoctov .... uhol na radian, delene, krat, ..... deje sa tam zaokruhlovanie, ...
konkretne mne to vrati:
1,22460635382238E-16
a to je solidne male cislo .... 0.00000000000000012246063538223773
takze ak je toto co ta trapi, tak si to radsej zaokruhli
alebo pri prevode zaformatuj napr. na 5 desatinych miest ....

sinus2alfa.Text = Convert.ToString(String.Format("{0:0.00000}",x));


Inak ked pouzivas Visual Studio, tak si F9-tkou nastav breakpoint na zaciatok funkcie a odkrokuj si to, vyvojove prostredie ma slusnu podporu k tomu, aby si si pozrel co sa nastaví do ktorej premennej ....


a este EDIT k predchadzajucemu:
double Alpha = (Math.PI / 180) * Fi;

v skutocnosti to bolo v poriadku, sry, ak je výsledná premenna a aspon jeden operand typu double, delí sa normalne ....
no je prakticke to tam pisat, aspon to nezavadza ....

este taka poznamka:
sinus2alfa nie je prave stastny nazov pre textbox, .... oplati si osvojit si daku konvenciu:
textbox sinus2alfa ....... tbSin2Alfa
textbox sina_sins_cosa ...... tbSinA_SinA_CosA
...... ked potom pises kod a vies ze to chces do dakeho textboxu, tak len klepnes tb, a intellisense ti hned zacne napovedat s dostupnymi textboxami, co je lepsie ako si spominat na take ukrutne nazvy :)
obdobne:
Label lbl.....
Button btn
Satoshi (3)|31.12.2010 10:32
Díky moc =) Jj mě vadilo to, že to házelo na -16, tak už to funguje díky moc ještě jednou :)

Jo ta konvence... ta je kvůli naší učitelce, která nemá ráda cokoliv pro ni nesrozumitelné...
Dojigiri (1629)|1.1.2011 21:13
Jinak doplním že obecně ve floating point neni úplně vhodný testovat 2 čísla přímo na rovnost (nebo číslo na rovnost s nulou), protože pak právě vzniká předchozí problém, kdy jsou čísla "skoro" stejný, ale ne úplně přesně (problém nepřesné reprezentace čísel v počítači).

Test rovnosti dvou čísel ve float nebo double je vhodnější dělat porovnáním absolutní hodnoty rozdílu těchhle čísel s nějakou dostatečně malou hodnotou, tj něco ve smyslu

if (abs(a-b) <= Epsilon) {
// Cisla se rovnaji.
} else {
// Cisla se nerovnaji.
}

Za epsilon se dá zvolit např. třeba 0.000001 apod. ... samozřejmě, aby to fungovalo obecně (např. i pro hodně malý čísla, anebo naopak pro hodně velký), by epsilon mělo záviset i na velikosti porovnávaných čísel, takže např. nejdřív spočítat

Epsilon = max(abs(a), abs(b)) * 1E-9;

(v ideálním případě by stačilo to udělat pouze z abs(a) bez maxima, jenže to by nefungovalo pokud by "a" bylo 0).

Nejvhodnější je dát si to do funkce, pojmenované např. epsilonEquals ;-)