Fórum pro uživatele kancelářského balíku OpenOffice | LibreOffice
 

#1 10. 8. 2018 06:30:13

mrmr9
Člen
Registrace: 10. 8. 2018
Příspěvků: 5

Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

Verze: 5.4.6.2 pro Mac, možná i jiné:
Nevím, kde je chyba, ale  procedura níže vrátí výsledek 1730 namísto očekávaných 1731. Pro jiné hodnoty např. 1,732 nebo 1,7311 a pod. funguje korektně a vrací očekávaný výsedek tedy např. 1732 nebo 1731. Zlobí to jen pro hodnotu 1,731, se kterou se provede nějaký výpočet. Samotné int(1731) vrací správný výsledek 1731.

Sub Main
Cislo=1.731
Print(Int(cislo*1000))
End Sub

Obdobný výpočet používám ve funkci na zkrácení čísla na 3 desetinná místa:
vysledek=int(x*1000)/1000 resp univerzální funkce pro zkrácení čísla na určitý počet desetinných míst.

Tuší někdo, proč tak elementární výpočet zlobí u téhle jediné hodnoty (možná jich bude víc, ale zatím jsem na jinou nenarazil).
Jak to napsat, aby se na výpočet dalo spolehnout?

Offline

#2 10. 8. 2018 09:19:05

neutr
Člen
Registrace: 8. 3. 2007
Příspěvků: 3,468

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

mrmr9 napsal(a)

Verze: 5.4.6.2 pro Mac, možná i jiné:
Nevím, kde je chyba, ale  procedura níže vrátí výsledek 1730 namísto očekávaných 1731. Pro jiné hodnoty např. 1,732 nebo 1,7311 a pod. funguje korektně a vrací očekávaný výsedek tedy např. 1732 nebo 1731. Zlobí to jen pro hodnotu 1,731, se kterou se provede nějaký výpočet. Samotné int(1731) vrací správný výsledek 1731.

Sub Main
Cislo=1.731
Print(Int(cislo*1000))
End Sub

Obdobný výpočet používám ve funkci na zkrácení čísla na 3 desetinná místa:
vysledek=int(x*1000)/1000 resp univerzální funkce pro zkrácení čísla na určitý počet desetinných míst.

Tuší někdo, proč tak elementární výpočet zlobí u téhle jediné hodnoty (možná jich bude víc, ale zatím jsem na jinou nenarazil).
Jak to napsat, aby se na výpočet dalo spolehnout?

     Já mám dojem že chyba je v zápisu toho INT - tato funkce zaokrouhluje. Takže jde spíš o to, jak opravdu vypadají čísla. Otestujte :

Sub Main
 Cislo=1.731
 Print cislo*1000
End Sub

     Je mi jasné že je to pod nějakým složitějším výpočtem a nedá se takto snadno dovodit proč to někdy jde a někdy nikoliv. Ale domnívám se že správné řešení by mohlo být například takto :

Sub Main
 Cislo=1.731
 Print INT(cislo*10000)/10
  'Nebo třeba
 Print INT((cislo*10000)/10)
End Sub

     Nicméně potvrzuji, že jde o chybu kterou dělá také verze Libre Office: 6.1.0.3
ID sestavení: efb621ed25068d70781dc026f7e9c5187a4decd1
Vlákna CPU: 2; OS: Windows 10.0; Vykreslování UI: výchozí;
Národní prostředí: cs-CZ (cs_CZ); Calc: group threaded


Moje e-mailová adresa
Pokud je Váš problém vyřešen, označte prosím svůj příspěvek za "VYŘEŠENÝ"
Zlepšíte orientaci při vyhledávání řešení JAK OZNAČIT TÉMA ZA VYŘEŠENÉ

Offline

#3 10. 8. 2018 11:25:39

lp.
Člen
Registrace: 24. 9. 2009
Příspěvků: 844

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

O žádnou chybu se nejedná. Je to vlastnost.

INT zaokrouhluje dolů na nejbližší celé číslo.

Použijte např. Int(cislo*1000 + 1e-13) nebo normálně zaokrouhlujte

Offline

#4 10. 8. 2018 15:14:34

mrmr9
Člen
Registrace: 10. 8. 2018
Příspěvků: 5

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

neutr napsal(a)
mrmr9 napsal(a)

Verze: 5.4.6.2 pro Mac, možná i jiné:
Nevím, kde je chyba, ale  procedura níže vrátí výsledek 1730 namísto očekávaných 1731. Pro jiné hodnoty např. 1,732 nebo 1,7311 a pod. funguje korektně a vrací očekávaný výsedek tedy např. 1732 nebo 1731. Zlobí to jen pro hodnotu 1,731, se kterou se provede nějaký výpočet. Samotné int(1731) vrací správný výsledek 1731.

Sub Main
Cislo=1.731
Print(Int(cislo*1000))
End Sub

Obdobný výpočet používám ve funkci na zkrácení čísla na 3 desetinná místa:
vysledek=int(x*1000)/1000 resp univerzální funkce pro zkrácení čísla na určitý počet desetinných míst.

Tuší někdo, proč tak elementární výpočet zlobí u téhle jediné hodnoty (možná jich bude víc, ale zatím jsem na jinou nenarazil).
Jak to napsat, aby se na výpočet dalo spolehnout?

     Já mám dojem že chyba je v zápisu toho INT - tato funkce zaokrouhluje. Takže jde spíš o to, jak opravdu vypadají čísla. Otestujte :

Sub Main
 Cislo=1.731
 Print cislo*1000
End Sub

     Je mi jasné že je to pod nějakým složitějším výpočtem a nedá se takto snadno dovodit proč to někdy jde a někdy nikoliv. Ale domnívám se že správné řešení by mohlo být například takto :

Sub Main
 Cislo=1.731
 Print INT(cislo*10000)/10
  'Nebo třeba
 Print INT((cislo*10000)/10)
End Sub

     Nicméně potvrzuji, že jde o chybu kterou dělá také verze Libre Office: 6.1.0.3
ID sestavení: efb621ed25068d70781dc026f7e9c5187a4decd1
Vlákna CPU: 2; OS: Windows 10.0; Vykreslování UI: výchozí;
Národní prostředí: cs-CZ (cs_CZ); Calc: group threaded

Díky za reakci. Print(Cislo*1000) odzkoušeno, výsledek 1731, tam problém není. Problém je při použití INT (případně i FIX). Zajímavé je, že když je v kódu jen Print(INT(1731)), je to ok a výsledek je korektní 1731. Jakmile se ale udělá int z hodnoty 1731, která vznikne výpočtem, tak je hodnota INT chybná. Přitom výsledky výpočtu jsou ok.

Ten druhý příklad, resp. obě varianty - vynásobit o řád víc a podělit deseti kupodivu funguje pro 1,731 bez chybně. Nevím ale, jestli se na to dá spolehnout pro další čísla :-( Zpracovávám těch hodnot několik tisíc, kde pro některá porovnání potřebuju číslo zaříznout za třetím desetinným místem bez zaokrouhlení.

Zkusil jsem testnout tohle:

Sub Main
For N = 1000 to 2000
	X = INT((N/1000)*1000)
	Y = FRAC((N/1000)*1000)
	If X <> N Then MsgBox("Chyba " & X & "  " & N & "  " & Y)
Next N
End Sub

Teoreticky by to mělo proběhnout bez zobrazení chyby, ale vyhazuje to chybu na více hodnotách, zpravidla lichých. Tak to asi nebude problém jediného čísla a moc bych se na funkce INT a FIX nespoléhal.

Nevím kam nebo jak se to dělá, ale dá se ten problém někam vyreportovat, aby to časem někdo opravil?

Offline

#5 10. 8. 2018 15:34:01

mrmr9
Člen
Registrace: 10. 8. 2018
Příspěvků: 5

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

lp. napsal(a)

O žádnou chybu se nejedná. Je to vlastnost.

INT zaokrouhluje dolů na nejbližší celé číslo.

Použijte např. Int(cislo*1000 + 1e-13) nebo normálně zaokrouhlujte

Tomu moc nerozumím, jak to souvisí s mým příkladem:

Sub Main
Cislo=1.731
Print(Int(cislo*1000))
End Sub

Kolik je podle vás 1,731 x 1000 ? Podle mě to je 1731 a nikoliv 1730,99999999999999999999......
Tady není přece co zaokrouhlovat.

Offline

#6 10. 8. 2018 17:03:46

neutr
Člen
Registrace: 8. 3. 2007
Příspěvků: 3,468

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

Opravdu je to chyba i když jsem netestoval mnoho variant. Možná jde o to, že výpočet je realizován logaritmováním a zde je něco upraveno kvůli zrychlení nebo jde o obyčejný kiks.
     Právě proto jsem doporučil zvětšit číslo a ořezat až podíl na správnou velikost. Také je dost dobře možné, že tato chyba přetrvává hodně dlouho. Nevyskytuje se vždy a těžko se něco takového hledá. Faktem je, že když by se jednalo o prosté vynásobení chyba nevznikne. Takže pro omezení desetinných míst musíte pro jistotu vynásobit o řád výše, podělit tou desítkou a tohle poslat na ořezání i když i tohle by se mělo důkladně otestovat.
     Jde o to odkud čísla berete. Může jít o přesnost podle zobrazení a tam by se to asi mohlo stát - vidíte zaokrouhlenou hodnotu kterou načítáte. Ale tady je zřejmé, že je to chyba i bez načítání zaokrouhlených hodnost.
     Někdy by bylo potřeba zaokrouhlit jinak - běžně potřeba účetních osnov, daňových přiznání ap. Na to by platila asi emulace vzorců sešitu, nebo vypálení vzroce makrem někam kde to nevadí, načíst zpětně jen jako hodnotu, pomocný vzrec smazat a je po legraci.

Editoval neutr (10. 8. 2018 17:07:50)


Moje e-mailová adresa
Pokud je Váš problém vyřešen, označte prosím svůj příspěvek za "VYŘEŠENÝ"
Zlepšíte orientaci při vyhledávání řešení JAK OZNAČIT TÉMA ZA VYŘEŠENÉ

Offline

#7 10. 8. 2018 17:58:02

lp.
Člen
Registrace: 24. 9. 2009
Příspěvků: 844

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

Možná by bylo vhodné se seznámit se způsobem, jak jsou v počítači uložena čísla s pohyblivou desetinnou čárkou. Např.:

https://cs.wikipedia.org/wiki/Pohybliv% … D%C3%A1rka

Jak to v programu obejít jsem už napsal.

Offline

#8 10. 8. 2018 18:09:42

lp.
Člen
Registrace: 24. 9. 2009
Příspěvků: 844

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

mrmr9 napsal(a)

[Kolik je podle vás 1,731 x 1000 ? Podle mě to je 1731 a nikoliv 1730,99999999999999999999......
Tady není přece co zaokrouhlovat.

Asi se budete muset smířit s tím, že zadaná čísla program neukládá přesně tak, jak byla zadána, ale převede je na jejich přibližnou hodnotu. S těmito přibližnými hodnotami pak provádí výpočty v plovoucí čárce. To také není matematicky úplně přesná operace.

Prostě, používat INT pro zaokrouhlování není dobrý nápad.

Offline

#9 11. 8. 2018 10:22:24

mrmr9
Člen
Registrace: 10. 8. 2018
Příspěvků: 5

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

neutr napsal(a)

Opravdu je to chyba i když jsem netestoval mnoho variant. Možná jde o to, že výpočet je realizován logaritmováním a zde je něco upraveno kvůli zrychlení nebo jde o obyčejný kiks.
     Právě proto jsem doporučil zvětšit číslo a ořezat až podíl na správnou velikost. Také je dost dobře možné, že tato chyba přetrvává hodně dlouho. Nevyskytuje se vždy a těžko se něco takového hledá. Faktem je, že když by se jednalo o prosté vynásobení chyba nevznikne. Takže pro omezení desetinných míst musíte pro jistotu vynásobit o řád výše, podělit tou desítkou a tohle poslat na ořezání i když i tohle by se mělo důkladně otestovat.
     Jde o to odkud čísla berete. Může jít o přesnost podle zobrazení a tam by se to asi mohlo stát - vidíte zaokrouhlenou hodnotu kterou načítáte. Ale tady je zřejmé, že je to chyba i bez načítání zaokrouhlených hodnost.
     Někdy by bylo potřeba zaokrouhlit jinak - běžně potřeba účetních osnov, daňových přiznání ap. Na to by platila asi emulace vzorců sešitu, nebo vypálení vzroce makrem někam kde to nevadí, načíst zpětně jen jako hodnotu, pomocný vzrec smazat a je po legraci.

Díky za upřesnění. napoprvé mi nějak nedošlo, že posunutím o řád výš a zaoruhlením se mohu dostat na požadovaný výsledek bez ohledu na nepřesnost výpočtu násobení na x-tém desetinném místě.

Offline

#10 11. 8. 2018 10:34:33

mrmr9
Člen
Registrace: 10. 8. 2018
Příspěvků: 5

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

lp. napsal(a)
mrmr9 napsal(a)

[Kolik je podle vás 1,731 x 1000 ? Podle mě to je 1731 a nikoliv 1730,99999999999999999999......
Tady není přece co zaokrouhlovat.

Asi se budete muset smířit s tím, že zadaná čísla program neukládá přesně tak, jak byla zadána, ale převede je na jejich přibližnou hodnotu. S těmito přibližnými hodnotami pak provádí výpočty v plovoucí čárce. To také není matematicky úplně přesná operace.

Prostě, používat INT pro zaokrouhlování není dobrý nápad.

Tomu vcelku rozumím, že procesor asi neprovádí výpočty v desítkové soustavě a na určitém desetinném místě dojde k zaokrouhlení, resp. nepřesnosti. To by mělo řešit povýšení o řád a zaokrouhlení případně váš návod, jak to obejít. Díky za něj.
Rozumím i tomu, že takové nepřesné číslo se pak uloží do proměnné.
Ovšem hlava mi fakt nebere, proč když si tu proměnnou zobrazím po násobení, zobrazí se zaokrouhlená. Je to někde popsané, že funkce Print nebo MsgBox zaokrouhluje? Případně poradíte, jak si pro kontrolu zobrazit sutečně uložený obsah proměnné, se kterým probíhají výpočty a ne zaokrouhlený? Pokud Print zaokrouhluje a je to někde popsané, pak ok. Pokud ne, tak potom kód viz. níže se nutně musí nejen mě jevit jako chyba.

Cislo = 1.731*1000
Print(Cislo) REM zobrazí 1731
Print (INT(Cislo)) REM zobrazí 1730

Offline

#11 11. 8. 2018 11:28:59

neutr
Člen
Registrace: 8. 3. 2007
Příspěvků: 3,468

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

Šlo by použít buď přepočítání do proměnné a tu zobrazit v PRINT, nebo MsgBox.
     MsgBox je příkaz i funkce. Dá se nastavit k ladění třeba tak jak popisujete pomocí proměnné, ale můžete otestovat i MsgBox i když to není tak jednoduché jako print :
Dim iVar, Cislo as integer
Cislo = 1.731*1000
iVar = MsgBox(Cislo,4,"Test čísla")
IF iVar = 7 Then : Stop : End if
     Také můžete otestovat funkci kterou budete Volat například z knihovny Moje makra Standard (nad všemi moduly) :

Public Function TestCis(ByVal iValue as variant)
Dim iVar as integer
iVar = MsgBox(iValue,4,"Test čísla")
IF iVar = 7 Then : Stop : End If
End Function

     Tato funkce se dá volat dvojím způsobem. Jednat v makru TestCis(1.731*1000), nebo ze sešitu jako vzorec =TestCis(1.731*1000). Takže když například zkrátíte název - aby jste si ho pamatoval - například TeCi, nebo CIST (CI_slo te_ST( tak máte snadnější a univerzálnější prostředek.

Editoval neutr (11. 8. 2018 11:32:07)


Moje e-mailová adresa
Pokud je Váš problém vyřešen, označte prosím svůj příspěvek za "VYŘEŠENÝ"
Zlepšíte orientaci při vyhledávání řešení JAK OZNAČIT TÉMA ZA VYŘEŠENÉ

Offline

#12 12. 8. 2018 01:03:50

lp.
Člen
Registrace: 24. 9. 2009
Příspěvků: 844

Re: Chybný výsledek funkce int() v makru pro vypočtený argument 1,731

Číslo 1,731 je binárně (typ double) uloženo jako 1.73099994659423828125, chyba vzniklá uložením a převodem je -5.340576171875E-8

Print zaokrouhluje. Nepamatuji se ale, kde jsem to viděl popsané, v dokumentaci LO určitě ne - nehledal jsem to tam, špatně se v ní hledá.

K přesnosti: lze použít Format(Cislo, "0.#####################") nebo, pokud se chcete podívat jen na chybu
Cislo = 1,731 * 1000 - 1731

Jinak souhlasím s Vámi, že je chybou, pokud ladící nástroje neukáží skutečnou hodnotu proměnné.

Offline

Zápatí