Jít do obsahu fóra

Nejsi přihlášen. Přihlas se nebo se zaregistruj.


Audioweb.cz » Smetiště » Zahadný problém v Delphi

  Stránky: 1

RSS

Příspěvky [8]

Téma: Zahadný problém v Delphi

Vytvořil jsem vypisování názvů jednotlivých sekcí z ini souboru podle hledané hodnoty v sekci, konkrétně vyhledávání podle Re.

Ukázka sekce v ini souboru:

[18Sound 10NMB420]
Qms=4,6
Qes=0,36
fs=65
Mms=31,5
Dd=20,5
Re=10,5
Hc=12
Hg=8
Pe=350
Le=0,4
URL=http://www.eighteensound.com/

Co je zajímavé, že pokud je Re=2,5, tak zadáním rozmezí při vyhledávání 2,5 a 2,5 (min (Edit123) a max (Edit124)) podle tohoto kódu:

with Relist do if Rebox.Checked then begin
Ref:=StrToFloat(ReadString(vypis.Strings[i],'Re',''));
if (Ref>=StrToFloat(Edit123.Text)) and (Ref<=StrToFloat(Edit124.Text)) then
Add(IntToStr(i)) else Add('-1') end else Add(IntToStr(i));

funguje, a položka je nalezena. A teď to příjde! Je-li hodnota 2,6, záznam se nenajde. Do max je nutné zapsat 2,601 a co je ještě zajímavější, že změním-li max na 2,60000000000000001 opět se nic nenajde a hodnota 2,60000000000000000000000000000001 je podle Delphi menší než 2,6. V případě hledání 2,7 je situace stejná. V případě 2,8 je nutno do minima zadat 2,79...


Co to má být? hmm2

(upravil The_P 14. 5. 2015 18:40)

Re: Zahadný problém v Delphi

Delphi neznam, ale obecne mne napada, ze je treba floaty porovnavat s nejakou toleranci, protoze float == float ti nemusi vratit true i kdyz jsou dle vypisu nutne stejne. Nasel jsem neco na SO: http://www.delphibasics.co.uk/RTL.asp?Name=CompareValue ale jak rikam, Delphi neznam takze nevim v jakem formatu jsou ty floaty ulozene v pameti apod, ani jestli ta fce je soucasti normalniho Delphi apod.

(upravil ythren 16. 5. 2015 19:38)

Re: Zahadný problém v Delphi

no ono číslo uložené jako float je vždycky nepřesné. čísla jako 2,60000000000000001 2,60000000000000000000000000000001 jsou už poněkud nad rámec přesnosti a prostě se ti z toho udělá nejbližší číslo co to zvládne, což může být např 2,5999999 nebo podobně. a zobrazování může být zaokrohlované.

float hodnoty se nedají použít na přímou shodu vždycky to musíš brát s určitou tolerancí například shoda by se dělalala jako

float tolerance =  0.1
float hledane = 2.6
float s_cim = 2.6

if ( (hledane >= (s_cim - tolerance)) and (hledane <= (s_cim + tolerance)) )

jistě si už domyslíš jak udělat větší nebo menší než s tolerancí

(upravil cestmir 14. 5. 2015 19:03)

Re: Zahadný problém v Delphi

Ako máš deklarovanú premennú Ref? Double? StrToFloat() totiž podľa http://delphi.about.com/library/rtl/blrtlStrToFloat.htm vracia Extended, čo je 80b float, ktorý sa pri priradení do 64b zaokrúhli a následne už jedno z >= && <= neplatí (tam sa zase ten Double padne na 80b a porovnajú sa 80b hodnoty). 2,6 má totiž v dvojkovej sústave nekonečný desatinný rozvoj, takže z princípu nemôže byť reprezentované exaktne. 2,5 má konečný.

V každom prípade ale platí, čo ti už napísali predrečníci, FP treba porovnávať vždy na rozsah, nie na rovnosť.

Iná možnosť, ak sú hodnoty v tom def. súbore zapísané v zaokrúhlenom desatinnom tvare, a potrebuješ hľadať len na prostú zhodu, je hľadať pomocou regulárneho výrazu (na spôsob "^\s*Re\s*=\s*0*2,60*"), napr. pomocou niektorej mutácie grep-u a nechať si vyplúvať vhodný kontext pred/za výskytom.

Re: Zahadný problém v Delphi

Moc dík kluci, tak to vidím na sprosté obejití ±0,001.

Re: Zahadný problém v Delphi

Teď si zas pro změnu už delší dobu lámu hlavu jak by šlo přepsat:

if key=vk_return then begin
if Sender=Edit1 then Edit2.SetFocus;
if Sender=Edit2 then Edit3.SetFocus;
end;

na case. Rozhodně tohle funguje jen pro přeskočení z Edit1, pak už ne:

if key=vk_return then case (Sender as TEdit).Tag of
1: Edit2.SetFocus;
2: Edit3.SetFocus;
end;

Taky by mě zajímalo jak to udělat na .Name.
Kód je v Edit1KeyDown a Edit2 z Object Inspectoru v OnKeyDown na něj odkazuje.


PS: Už jsem tak zblblej, že po dopsání tohodle textu jsem zmáčknul Ctrl+F9. big_smile

Re: Zahadný problém v Delphi

Pokud událost onKeyDown chytáš z objektu Edit1,  logicky bych čekal, že z objektu Edit2 nic nevyleze, když z něj událost nepochází.
Zkus událost chytat z vyšší instance, třeba z Formu.

PS: Nejsem odborník na delphi, jen občasný uživatel opensource konkurence - Lazarus-u

(upravil The_P 24. 5. 2015 7:35)

Re: Zahadný problém v Delphi

No, pokud vim Delphi a la Pascal neumi string v CASE, v Ccku se to delalo pomoci trebas strcmp() v kazdem bloku casu namisto abys tam dal cisla. Co jsem googlil, jedna z moznosti (ale ne elegantni zrovna):

Case StrIndex('SomeName', ['bobby', 'tommy', 'somename']) of 
  0: ..code.. ;//bobby
  1: ..code..;//tommy
  2: ..code..;//somename
else
  ShowMessage('error');
end.

Coz ale diky tomu ze stejne si musis dat na indexy pozor je takove nanic. Myslim ze ten IF/ELSEIF bude v tomhle lepsi v prehlednosti. Trebas nekdo se skutecnou zkusenosti poradi lepe ;/

PS: Jeste mne napadlo, pokud dokazes zjistit name, ty indexy jdou za sebou a dokazes ten setFocus zavolat na jakemkoliv jmenu, asi by bylo lepsi udelat to ciste programove s tim, ze inkrementujes to cislo v nazvu no ne? Pripadne pokud jsou tam nepravidelnosti, udelat si mapovaci tabulku (Jmeno1 => Jmeno2, Jmeno2 => JineJmenoX) a pak jen malym kodem dole to zpracovat. Ovsem tohle uz jen spekuluju, jak je tohle v delphi pohodlne fakt netusim. Ciste pro inspiraci...

Příspěvky [8]

  Stránky: 1

Audioweb.cz » Smetiště » Zahadný problém v Delphi

Podobná témata


~±«|»¼½¾²³&@µΩπØ$£