Ahoj, potreboval bych radu ohledne vypoctu s hodnotami typu double napr.
Dim c As Double
c = 760879.16 - 755769.087298
Me VBAcko vypocte c=5110.07270200003, ale vysledek by mel byt jen c=5110.072702, takze jde jen o tu 3ku kdesi vzadu.
Doted jsem vzdalenym desetinnym mistum nevenoval pozornost, tak nevim jestli to dela i pri jine operaci nez minus, ale
momentalne me tendle problem dost vadi, protoze musim vsude cpat funkci Round.. abych mel cislo na pozadovany pocet mist.
Vsem co se pokusi pomoct predem diky :)
Fórum › Visual Basic
Problem s presnosti vypoctu typu double
Neco sem vyGoogloval, ale v anglictine (coz neni nic pro me ), takze pokud ma nekdo po ruce odkaz na cesky stranky, tak sem s nim. Ale hlavni jsem asi pobral - hodnota neni ulozena jako sekvence cislic, ale jako exponent a cislo pro jeho prenasobeni. Rad bych ale vedel, najaky vztah nebo neco jak zjistit, jestli se me jeste cislo ulozi "spravne" nebo jestli se jiz vlivem systemu viz vyse ulozi jen nejblize mozna hodnota.
Neco sem vyGoogloval, ale v anglictine (coz neni nic pro me ), takze pokud ma nekdo po ruce odkaz na cesky stranky, tak sem s nim. Ale hlavni jsem asi pobral - hodnota neni ulozena jako sekvence cislic, ale jako exponent a cislo pro jeho prenasobeni. Rad bych ale vedel, najaky vztah nebo neco jak zjistit, jestli se me jeste cislo ulozi "spravne" nebo jestli se jiz vlivem systemu viz vyse ulozi jen nejblize mozna hodnota.
Sakra pomalej net 2x sipka zpet a pak zas nazpet a hodilo to znova post a mazani je zakazano...
Prave chci vedet, jestli je naka pomucka pro to, abych vedel kdy to 100% nemuze nastat. Jako treba, ze 5.5+3.4=8.9 a ne 8.9000000003 atd. jestli to ma treba vazbu na pocet platnych mist vstupnich hodnot nebo tak neco.
Dim a, b, c, d As Double
a = 760879.16
b = 755769.087298
d = b - a
a = 10 ^ 6 * a
b = 10 ^ 6 * b
c = (b - a) / 10 ^ 6
Todle me prijde hrozne divny, ze ten sami vypocet neni ekvivalentni (d<>c).
No dotaz zni, pokud budu tedy pocitat pouze s celymi cisly (viz priklad 12 platnych mist), bude vypocet vzdy presny? Nebo nakej odkaz/navod jak se s timdle vyrovnavaj profici.
Problém je v tom, že přes přesnost single/double se prostě nedostaneš. Když máš číslo 755769.087298, tak proč tě zajímá, jestli je to 755769.087297 nebo 755769.087299?
http://www.root.cz/clanky/norma-ieee-754-a-pribuzni-formaty-plovouci-radove-tecky/
Můžeš zkusit přejít na 64bitová celá čísla (patřičně vynásobit, aby si nepřišel o desetinnou část) ...
V tom co delam se hodnoty dale porovnavaji, casto s velice podobnymi cisly, takze u velke casti maji vyznam predevsim vzdalenejsi desetinna mista.
Nejspis jsem zvolil spatnej typ (nepotrebuju rozsah pro 300mistna hodnoty), potrebuju ale typ pro presne hodnoty s max.
8 misty vlevo od des. tecky a 6 des. misty, s dostatecnou rezervnou pro bezne matematicke operace s takovym cislem (nejvic
co pouziju je asi ^2).
Programuju ve VBA (pod Excelem 2003). Moc na vyber typu co by splnoval pozadavky viz vyse asi nemam - Currency ma dost maly rozsah a Decimal neni momentalne podporovan, nicmene je pry soucasti typu, kteremu jsem se doted snazil radsi vyhybat - Variant (16 bytes). Uz ted (jsem cca. v pulce programu) trva vypocet pri prumernem vtupnim objektu (cekam i 10x vetsi)
cca 5 minut... tak doufam, ze nebude mit ten Variant nakej drastickej vliv na narust vypocetniho casu.
Variant není to co hledáš. Variant je typ používaný pro COM Automation a lze do něj "schovat" jakýkoliv jiný typ.
Napadají mě 2 možnosti. Buď proveď "převod" na celá čísla (vynásobit dostatečně velkým číslem). Nebo pokud porovnáváš 2 floatová čísla a liší se na x-tém desetinném čísle, tak provést jejich rozdíl a porovnávat, jestli je ten rozdíl <= než nějaký "epsilon".
Co se pise ve VBA:
Variant(with numbers) 16 bytes Any numeric value up to the range of a Double .
Variant(with characters) 22 bytes + string length Same range as for variable-length String
+ teda dokaze zapsat cokliv jinyho
Takze jakmile napisu neco jako:
Dim a as Variant
a=755769.087297 'zapise hodnotu nejspis jako naky floatovy typ (double?)
a=CDec(755769.087297) 'zapise hodnotu jako Decimal - coz me prijde jako jediny reseni
Problem je, ze nevim o zadnym celociselnym typu, ktery by hodnotu po prenasobeni uchoval (nebo s ni jeste mohl provadet matematicke operace).
Ty cisla co porovnavam se klidne lisi i v nejvyssim radu (nicmene vetsi cast se bude lisit nekde dal), ale pokud bych to pouzil, tak prave netusim, jak urcit desetinny rad (nebo to epsilon). Proste kde konci presnost hodnoty a zacinaji cislice nejblize mozne ulozitelne hodnoty daneho typu.
A proč nepoužíváš typ Decimal přímo? Tím, že ho "schováváš" do Variantu si vlastně umýslně ještě zpomaluješ program, protože se před každým výpočtem musí zjisit, jakého typu je hodnota schovaná ve Variantu. A jinak je to dobrá volba, resp. podle toho co píšou v dokumentaci je z principu přesnější než double (je to vlastně ta první možnost, o které jsem psal).
Epsilon si volíš ty, tím říkáš jakou chceš dosáhnout přesnost.
Decimal primo.. viz par postu zpet, decimal neni momentalne ve VBA podporovan. Primo se tam pise, ze k jeho pouziti se ma pouzit Variant (jehoz podtypem Decimal je) s pretypovanim CDec.
No ja chci presnost co nejvyssi, ale nema prece cenu porovnavat uplne konce hodnot, kde si float typ "pise co chce", chtel bych porovnavat jen po cast co je "presne". Nedokazu si prestavit co se jeste zapise naprosto presne a co jiz se musi nahrazovat hodnotou nejblizsi. Nebo jestli ma vubec cenu u floatu pouzivat neco jako If a=b then... vzhledem k tomu, ze stejna hodnota muze byt zapsana pokazde trosku jinak.
Aha, tak s tím Decimal mi to nějak uniklo.
A ta přesnost ... pro float opravdu skoro nemá smysl if (a == b) then ..., ale (zrovna nedávno to tu proběhlo v PHP) právě přes epsilon nebo jinak řečeno přes zvolenou přesnost tj. něco jako:
if (abs(a - b) <= epsilon) then ...
Jak jsem psal, epsilon si volíš sám. A pokud tvoje volba to nejmenší možné, tak to je závislé na "mašině". Některé jazyky ho umí vyčíslit (nebo se o to alespoň snaží): VB Double.Epsilon = 4.94065645841247e-324, ale to není přesnost daná strojem, ale nejmenší kladná hodnota větší než 0. Neboli asi bude potřeba zapojit strejdu googla (možná i tetu wiki :smile1: ) a pokud nic neporadí, tak si zvolit svojí přesnost (experimentálně zjištěnou a vyhovující).
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Jmeno pole typu double — založil cecil
Proměnné typu float, double — založil DiAnno
Problem s double — založil braba
Mám problém s double přihlašováním — založil jAkErCZ
Problem s prevodem typu(?) + tridama — založil jak
Moderátoři diskuze