Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Funkcja zaokrąglania do 2-ch miejsc po przecinku.

2,738 views
Skip to first unread message

pie...@yato.pl

unread,
Oct 5, 2007, 10:49:16 AM10/5/07
to
Witam,
Istnieje w VBA funkcja Round(X,n), która ma w zamyśle zaokrąglać
liczbę X do n miejsc po przecinku. I funkcja działa, ale niekoniecznie
zgodnie z naszymi rodzimymi warunkami zaokrąglania (np. wartości na
fakturach)
Np. jesli chcemy zaokrąglić liczbę 10,2550 do 2-ch miejsc po przecinku
funkcja ta zwróci 10,25 zamiast wymaganych u nas 10,26. A w
pozostałych przypadkach działa OK.

I co ? Ja jednak upieram się, żeby mi Access liczył prawidłowo i
wydaje się (poza oczywiście funkcją Format - bardzo przeze mnie nie
lubianą), że trzeba po prostu napisać własną funkcję, która zrealizuje
poprawnie to zadanie.
Zatem - popełniłem ją modyfikując nieco rozwiązanie podane na tej
grupie przez s.c.o.r.p.i.o jeszcze w 2004 r.

1) najpierw z liczby należy wyodrębnić rozwinięcie dziesiętne:
R=Abs(X)-Abs(Fix(X)
2) Potem sprawdzić wartość cyfry na 3-cim miejscu po przecinku:
Ta cyfra to: Fix(R*1000) - (10 * Fix(R*100)
3) Jeśli 3-cia cyfra po przecinku jest równa 5, to powinniśmy
zaokrąglić w górę
X=Round(X,2)+0,01
4) jeśli jest inaczej - to X=Round(X,2)


Funkcja jest oczywiście banalna i niewarta może wzmianki na tym forum
pełnym tuzów Accessa (niektórych poczynania śledzę i stosuję ich
wskazówki i rozwiązania od lat), gdyby nie wystąpił pewien problem:

Napisałem kod, sprawdzam i co ? Ta funkcja nie zawsze działa
poprawnie! Gdzie jest do cholery błąd? Przecież trudno zarzucić coś
nielogicznego w moim rozumowaniu...

A jednak błąd jest - bo zapomniałem, że np. liczba 0,005 wyświetlana
na ekranie, nie zawsze jest tą liczbą dla komputera,który liczy zero-
jedynkowo. Dla komputera 0,005 to np. 0,004999999999. Stąd próbując
liczyć coś, co na papierze wygląda jako Fix(0,005*1000) - (10 *
Fix(0,005*100) = 5 wychodziło mi jako Fix(0,0049999 *1000) -
(10*Fix(0,004999*100) = 4 (a nie 5).

Rozwiązaniem okazała się - o dziwo - funkcja Round, której nakazałem
zaokrąglenie do 4-ch miejsc po przecinku i dalej już poszło.
POniżej rezultat

Public Function BPRound(X As Double) As Double
Dim R, S, x100, x1000 As Double
If IsNull(X) Then
BPRound = 0
Else
S = Abs(X) - Abs(Fix(X)) ' reszta dziesiętna - moduł

x100 = Round(S, 4) * 100 ' reszta * 100
x1000 = Round(S, 4) * 1000 ' reszta * 1000
x100 = Fix(x100)
x1000 = Fix(x1000)

If x1000 - (10 * x100) >= 5 Then
R = 0.01 + (x100 / 100)
Else
R = x100 / 100
End If

If Sgn(X) = 1 Then
BPRound = Fix(X) + R
Else
BPRound = Fix(X) - R
End If
End If
End Function

Krzysztof Naworyta

unread,
Oct 5, 2007, 11:14:29 AM10/5/07
to
Użytkownik <pie...@yato.pl> napisał:


(...)


| Np. jesli chcemy zaokrąglić liczbę 10,2550 do 2-ch miejsc po przecinku
| funkcja ta zwróci 10,25 zamiast wymaganych u nas 10,26. A w
| pozostałych przypadkach działa OK.

jest to tzw. zaokrąglenie bankowe, do najbliższej parzystej.

| I co ? Ja jednak upieram się, żeby mi Access liczył prawidłowo i
| wydaje się (poza oczywiście funkcją Format - bardzo przeze mnie nie
| lubianą), że trzeba po prostu napisać własną funkcję, która zrealizuje
| poprawnie to zadanie.
| Zatem - popełniłem ją modyfikując nieco rozwiązanie podane na tej
| grupie przez s.c.o.r.p.i.o jeszcze w 2004 r.
|
| 1) najpierw z liczby należy wyodrębnić rozwinięcie dziesiętne:
| R=Abs(X)-Abs(Fix(X)
| 2) Potem sprawdzić wartość cyfry na 3-cim miejscu po przecinku:
| Ta cyfra to: Fix(R*1000) - (10 * Fix(R*100)
| 3) Jeśli 3-cia cyfra po przecinku jest równa 5, to powinniśmy
| zaokrąglić w górę
| X=Round(X,2)+0,01
| 4) jeśli jest inaczej - to X=Round(X,2)

(...)


pozostaje do kompletu dorzucić coś straaasznie starego :)))

http://www.access.vis.pl/af0808.htm

--
KN

0 new messages