Vlákna: 292
Příspěvky: 5 997
Registrace: 2007
Jméno: Antonín Richter
Bydliště: Brno
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:
Kód: [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:
Kód: 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?
Vlákna: 2
Příspěvky: 271
Registrace: 2010
Jméno: Petr
Bydliště: Praha (Kladno)
14. 5. 2015, 19:39
(poslední úprava: 14. 5. 2015, 19:40 | The_P)
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.
Vlákna: 5
Příspěvky: 217
Registrace: 2011
14. 5. 2015, 19:44
(poslední úprava: 16. 5. 2015, 20:38 | ythren)
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í
Vlákna: 1
Příspěvky: 553
Registrace: 2012
Bydliště: BA
14. 5. 2015, 19:50
(poslední úprava: 14. 5. 2015, 20:03 | cestmir)
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.
Vlákna: 292
Příspěvky: 5 997
Registrace: 2007
Jméno: Antonín Richter
Bydliště: Brno
Moc dík kluci, tak to vidím na sprosté obejití ±0,001.
Vlákna: 292
Příspěvky: 5 997
Registrace: 2007
Jméno: Antonín Richter
Bydliště: Brno
Teď si zas pro změnu už delší dobu lámu hlavu jak by šlo přepsat:
Kód: 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:
Kód: 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.
Vlákna: 13
Příspěvky: 1 767
Registrace: 2013
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
Vlákna: 2
Příspěvky: 271
Registrace: 2010
Jméno: Petr
Bydliště: Praha (Kladno)
24. 5. 2015, 8:30
(poslední úprava: 24. 5. 2015, 8:35 | The_P)
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):
Kód: 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...
|