Witam!!!
Proszę o podpowiedź gdzie leży przyczyna błędu.
Mam makro w którym w jednej z procedur deklaruję zmienną Ilosc jako single (dim Ilosc as single)
Pobieram wartość komórki z jednego arkusza do tej zmiennej a następnie w innym miejscu procedury kopiuję do komórki w innym arkuszu.
poleceniami
oCell=oSheet.getcellbyposition (2,Numer_wiersza+6)
Ilosc=oCell.value
a następnie po uaktywnieniu odpowiedniego arkusza i wybraniu komórki docelowej
oCell.value=Ilosc
'
Problem polega na tym, że przenoszona wartość w komórce źródłowej ma wartość np. =3,08
a po przeniesieniu wartość ta= 3,799999 i jeszcze parę cyfr.
Problem znika gdy zmiennej "Ilosc" w procedurze nie deklaruję jako single
Nie rozumiem dlaczego tak się dzieje.
Pozdrawiam
Problem z przenoszeniem wartości
Problem z przenoszeniem wartości
open Office 4 na win7
Re: Problem z przenoszeniem wartości
W helpie jest napisane:wojtul60 pisze:Problem polega na tym, że przenoszona wartość w komórce źródłowej ma wartość np. =3,08
a po przeniesieniu wartość ta= 3,799999 i jeszcze parę cyfr.
Zmienne typu Single
Zmienne typu Single (pojedyncza precyzja) mogą przyjmować wartości dodatnie lub ujemne w zakresie od 3,402823 x 10E38 do 1,401298 x 10E-45. Są to zmienne zmiennoprzecinkowe, w których wraz ze wzrostem wartości części całkowitej zmniejsza się precyzja części ułamkowej. Zmienne typu Single są odpowiednie do obliczeń matematycznych o średniej dokładności. Obliczenia wymagają więcej czasu niż w przypadku zmiennych całkowitych, ale są szybsze niż w przypadku zmiennych typu Double (podwójna precyzja). Zmienna typu Single wymaga czterech bajtów pamięci.
To że nie deklaryujesz typu zmiennej nie oznacza że basic nie deklaruje jej typu automatycznie:wojtul60 pisze:Problem znika gdy zmiennej "Ilosc" w procedurze nie deklaruję jako single
Nie rozumiem dlaczego tak się dzieje.
Kod: Zaznacz cały
Variant/double
Pewnym rozwiązanie jest deklaracja jako string (w pamięci: 1 + 1 na każdy znak), a później w kodzie konwersja na typ double (choć pewien na 100% nie jestem).
Kod: Zaznacz cały
Cell.value = Cdbl(ilosc)
Kod: Zaznacz cały
Dim ilosc as String*3
Więc kod mógłby wyglądać tak:
Kod: Zaznacz cały
Sub test
Dim ilosc as String
'Dim ilosc as String * 4
Dim Doc As Object
Dim Sheet As Object
Dim Cell As Object
Doc = ThisComponent
Sheet = Doc.Sheets(0)
Cell = Sheet.getCellRangeByName("A1")
ilosc= cell.string
Cell = Sheet.getCellRangeByName("A2")
Cell.value = Cdbl(ilosc)
End Sub
LibreOffice 5.1.2.2 Ubuntu 16 LTS
Re: Problem z przenoszeniem wartości
Witam!!!
Te informacje z pomocy były mi znane- ale wydawało mi się że 4 bajty wystarczą na wartość 3,08.
Nie wiem jak OO wykorzystuje te cztery bajty które ma do dyspozycji na zmienne typu single i mimo że w moim przypadku po przecinku są tylko
dwie cyfry znaczące to jak widać nie jest to takie proste.
Dzięki
Te informacje z pomocy były mi znane- ale wydawało mi się że 4 bajty wystarczą na wartość 3,08.
Nie wiem jak OO wykorzystuje te cztery bajty które ma do dyspozycji na zmienne typu single i mimo że w moim przypadku po przecinku są tylko
dwie cyfry znaczące to jak widać nie jest to takie proste.
Dzięki
open Office 4 na win7
Re: Problem z przenoszeniem wartości
Bajty wykorzystuje się tak, że wartości całkowitoliczbowe (integer, longint) są pamiętane w układzie dwójkowym, a wartości zmiennopozycyjne (single, double) jako pary liczb całkowitych. Pierwsza liczba przechowuje znak i cyfry znaczące, a druga względne położenie przecinka/kropki dziesiętnej. Każda z tych danych ma stałą pojemność, tj. liczbę pamiętanych cyfr dwójkowych.
Problem polega na tym, że ułamki binarne mają skończoną liczbę cyfr tylko wtedy, gdy opisują ułamki niewłaściwe o mianownikach będących potęgami dwójki. W przypadku ułamków dziesiętnych skończoność wymaga, by mianownik był iloczynem potęg dwójki i potęg piątki, to znaczy dzielników bazy systemu pozycyjnego.
Np. liczba 5/2 jako ułamek dziesiętny ma postać 2,5, a jako binarny 10,1. Natomiast 3,08 odpowiada ułamek 308/100 = 77/25, skąd widać, że odpowiedni ułamek binarny ma nieskończone rozwinięcie. Podobnie będzie z liczbą 0,1 == 1/10. Tak! komputery na ogół pamiętają wartość 0,1 z błędem!
W takim razie dlaczego w przypadku double tego nie ma? Jest, tylko nie widać. W uproszczeniu: konwersja single -> double nie zmniejsza błędu, tylko zwiększa precyzję zapisu. Podczas prezentacji wartości liczby dokonywana jest konwersja z double do napisu, która ukrywa/koryguje błąd na ostatniej cyfrze. Jeśli wcześniej skonwertowano wartość z single, błąd jest większy i nie jest korygowany.
Problem polega na tym, że ułamki binarne mają skończoną liczbę cyfr tylko wtedy, gdy opisują ułamki niewłaściwe o mianownikach będących potęgami dwójki. W przypadku ułamków dziesiętnych skończoność wymaga, by mianownik był iloczynem potęg dwójki i potęg piątki, to znaczy dzielników bazy systemu pozycyjnego.
Np. liczba 5/2 jako ułamek dziesiętny ma postać 2,5, a jako binarny 10,1. Natomiast 3,08 odpowiada ułamek 308/100 = 77/25, skąd widać, że odpowiedni ułamek binarny ma nieskończone rozwinięcie. Podobnie będzie z liczbą 0,1 == 1/10. Tak! komputery na ogół pamiętają wartość 0,1 z błędem!
W takim razie dlaczego w przypadku double tego nie ma? Jest, tylko nie widać. W uproszczeniu: konwersja single -> double nie zmniejsza błędu, tylko zwiększa precyzję zapisu. Podczas prezentacji wartości liczby dokonywana jest konwersja z double do napisu, która ukrywa/koryguje błąd na ostatniej cyfrze. Jeśli wcześniej skonwertowano wartość z single, błąd jest większy i nie jest korygowany.
JJ
LO (24.2|7.6) ∙ Python (3.12|3.11|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)
LO (24.2|7.6) ∙ Python (3.12|3.11|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)