Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno Pretypovanie real na integer mimo trunc - Delphi

Dobrý deň, priatelia, vedeli by ste mi, prosím, dať kvalifikovanú odpoveď na otázku, ako v Delphi 6 spoľahlivo pretypovať real alebo extended na integer? Vždy ma učili používať na to funkciu trunc, ktorá by vraj mala vrátiť celočíselnú časť z reálneho čísla. Prax mi však ukázala, že táto definícia nie je celkom správna. Neraz sa mi stalo, že moja aplikácia nepracovala celkom správne a často bol na vine práve príkaz trunc, ktorý vrátil nižšiu hodnotu najmä vtedy, ak parametrom bol nejaký výpočet alebo záporné číslo. Práve teraz tu mám relatívne jednoduchý prípad - užívateľ do editačného poľa vpíše reálne číslo, ktoré potom má byť vynásobené 1000 a ďalej už spracovávané ako celé číslo. Ak však do editačného poľa vpíšem -16.275 a urobím nasledovné operácie:
var x,y:real;i:integer;
x:= strtofloat(ansireplacetext( edit2.text,'.',',')); // prevediem si obsah edit pola na real - výsledok je -16,275;
y:=x*1000; // vynásobím 1000 - výsledok je -16275 v premennej typu real;
i:=trunc(y);
výsledkom nie je -16275 ale -16274. Takéto situácie sa mi stali už viackrát, preto hľadám spôsob, ako skutočne spoľahlivo pretypovať real na integer bez ohľadu na to, či je číslo kladné alebo záporné a dostať naozaj tú časť čísla, ktorá je pred desatinnou čiarkou. Vďaka.

Jsou zobrazeny jen nové odpovědi. Zobrazit všechny
Předmět Autor Datum
pme: vďaka, chyba bola skutočne v argumente typu real, pričom mal byť extended. Teraz to už naozaj p… nový
Stefan77 12.02.2016 19:00
Stefan77
Ani extended neni spravne. (mozu tam vzdy vznikat chyby pri tom zaokruhlovani, zavisi to od zadaneho… nový
MM.. 12.02.2016 19:29
MM..
BTW. vcera som aj hladal ze ci nahodou pri extended sa neuklada binarne inac, a ne, aspon podla toho… nový
MM.. 12.02.2016 19:42
MM..
Napr. tuto mas viac pokecu, ak by ta to nahodou zaujimalo. Vidiet tam jasne ze aj extended ma chyby,… poslední
MM.. 12.02.2016 20:00
MM..

pme: vďaka, chyba bola skutočne v argumente typu real, pričom mal byť extended. Teraz to už naozaj pracuje ako má. Ja som bol vždy vedený k tomu, aby som používal úsporné typy teda napr aj word alebo bite keď je zbytočné použiť integer a tak som aj v mojom projekte použil real namiesto extended, lebo som mal za to, že real je vzhľadom na počet použitých bitov úspornejší a ja sa hodnotami určite pohybujem v rozsahu -180000.000 až 180000.000 s počtom desatinných miest max 3, aj keď samozrejme chápem že sú obsadené aj ďalšie miesta za desatinnou čiarkou, ale pre prácu ich nepotrebujem a ignorujem.
MM: S tou raketou vystrelenou na mesiac a pristátim kilometer vedla si v podstate trafil kliniec po hlavičke, lebo aplikácia, na ktorej pracujem, prezerá mapu, takže tie čísla sú vlastne gps súradnice. Mám negraficky lineárne spracovanú databázu gps pozícií takmer celého sveta, pričom rozlíšenie je relatívne velké - až 3 desatinné miesta. Nemám ale jednotlivé body, ale plochy, určené lavým dolným a pravým horným rohom, takže napr 48.120,17.060 až 48.159,17.099 je Bratislava - Staré mesto. Pohybom šípky sa v podstate zvyšuje a znižuje latitúda a longitúda, čo by sa za normálnych okolností malo diať tak, že súradnice, zapísané v premenných typu real alebo extended by mali zvyšovať a znižovať hodnotu a teda by som k nim mal pripočítavať a odpočítavať niekde na úrovni tretieho miesta za desatinnou čiarkou. To ale v praxi práve spôsobuje tú výchylku, o ktorej si písal, po pár desiatkach či stovkách operácií si už niekde úplne inde, preto to robím tak, že súradnice sú vynásobené 1000 a samotný pohyb je rátaný tesne za desatinnou čiarkou. Tak sa posunieš napr zo 48120.000000 na 48159.7872, čo teraz treba vyhodnotiť a oznámiť, čo sa na danej súradnici nachádza. Keďže to za čiarkou je len pomocná hodnota pre rátanie pohybu a rozlíšenie mapy mám len na 3 desatinné miesta gps, to za čiarkou dám preč a výsledné 48159 zodpovedá latitúde 48.159 (rovnako tak aj s longitúdou). A práve tu je zaokrúhlenie kontraproduktívne, lebo kým 48.159 je ešte Bratislava staré mesto, 48.160 je už niečo iné. Preto som sa potreboval vyhnúť zaokrúhleniu a ak trunc vracalo chybný výsledok, tak som sa geograficky naozaj ocitol o kilometer inde.
Ešte raz vďaka všetkým.

BTW. vcera som aj hladal ze ci nahodou pri extended sa neuklada binarne inac, a ne, aspon podla toho co som nasiel specifikacie. Takze aj tam ti vznikyju chyby zapisu, neviem zhlavy preco to konkretne cislo zaokruhli u extended na to vyssie cislo (nechce sa mi to prevadzat rucne ani instalovat nejake delphi kvoli tomu :) ale moze to suvisiet len s tym konkretnym cislom a ine moze byt zas blbo.
Pri praci s plavajucou ciarkou musis musis vzdy mysliet aj na chybu zapisu a vypoctu, a pri konverziach sa to musi vzdy zaokruhlovat aspon s prihliadnutim na maximalnu moznu odchylku po tom vypocte, t.j. priratat si tam aspon tu ocakavanu max. chybu, apod.

Napr. tuto mas viac pokecu, ak by ta to nahodou zaujimalo. Vidiet tam jasne ze aj extended ma chyby, samozrejme.
articles-floats.html

Napr. zaujimave je aj toto

The x87 Floating Point Unit

The x87 FPU knows 4 rounding modes (see the FPU control word section of this article). So how does the FPU round? Say an operation on a Single produced an intermediate result that has some extra low bits. The extended mantissa looks like this:

1.0001 1100 0100 1100 1001 0111

The underlined bit is the bit to be rounded. There are two possible values this can be rounded to, the value directly below and the value directly above:

1.0001 1100 0100 1100 1001 011
1.0001 1100 0100 1100 1001 100

Now what happens depends on the rounding mode. If the rounding mode is the default — round to nearest “even” — it will get rounded to the value that has a 0 as least significant bit. You can probably guess which of the two values is chosen for the other rounding modes.

To by vysvetlovalo ze preco nahodou toto cislo v extended nahodou zaokruhluje tak, ale bude to zavisiet od zadaneho cisla (skusaj si rozne cisla alebo si urob program aby ti preskusal vsetky mozne cisla a vypisal ked to pri niektorom bude nespravne, a napis jak si dopadol :)

Zpět do poradny Odpovědět na původní otázku Nahoru