473,378 Members | 1,377 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Calculation Discrepancy

I have a module that contains a simple calculation:

R = (X * D) / V

All values are Double.

Using the following values:

X = 95
D = 10000
V = .0225

I get 42,222,222.22, but Access gives me 42,222,220.5444619.

How is Access calculating this and how can I correct it?
Sep 18 '07 #1
12 1883
Scott Price
1,384 Expert 1GB
Using a calculator, Excel spdsheet, and typing the values into an Access query design grid all produce exactly the same results for me: 42,222,222.22

Let's take a look at the whole code you are using for your function. Also, take a very close look at each data type, especially looking for any times they might go through declaration changes, i.e. from Integer to Double, etc.

Regards,
Scott

p.s. when pasting the code into this reply window, select all the code, wrap it in code tags by clicking the # sign above, and manually edit the first tab to look just like this: [code=vb] Thanks!
Sep 18 '07 #2
Thanks Scott,

Hopefully it's somewhere in here. Also in the table where the data is coming from X, V and D are Single.

Expand|Select|Wrap|Line Numbers
  1. Public Function cfuQBD(X As Double, V As Double, D As Double) As String
  2.     'X is raw count
  3.     'V is volume
  4.     'D is dilution
  5.  
  6.     Dim R As Double   'Formated Calculated Result
  7.     Dim DR As Double  'Lowest Dilution Result
  8.  
  9.     V = nz(V, 0)
  10.     D = nz(D, 1)
  11.  
  12.     If V = 0 Then
  13.         cfuQBD = vbNullString
  14.         Exit Function
  15.     End If
  16.  
  17.  
  18.     DR = Format(vbaRound((D / V), 0), "#,##0")       'Formated Lowest Dilution Result
  19.         If DR = 0 Then
  20.             DR = 1
  21.         End If
  22.  
  23.     R = Format(vbaRound(((X * D) / V), 0), "#,##0") 'Formated Calculated Resul
  24.  
  25.     Select Case X
  26.         Case Is <= 0
  27.             cfuQBD = "<" & DR
  28.         Case Is > 0
  29.             If R <= 0.5 Then
  30.                 cfuQBD = "<" & DR
  31.             Else
  32.                 cfuQBD = R
  33.             End If
  34.     End Select
  35.  
  36. End Function
Sep 19 '07 #3
Scott Price
1,384 Expert 1GB
Thanks Scott,

Hopefully it's somewhere in here. Also in the table where the data is coming from X, V and D are Single.

Expand|Select|Wrap|Line Numbers
  1. Public Function cfuQBD(X As Double, V As Double, D As Double) As String
  2.     'X is raw count
  3.     'V is volume
  4.     'D is dilution
  5.  
  6.     Dim R As Double   'Formated Calculated Result
  7.     Dim DR As Double  'Lowest Dilution Result
  8.  
  9.     V = nz(V, 0)
  10.     D = nz(D, 1)
  11.  
  12.     If V = 0 Then
  13.         cfuQBD = vbNullString
  14.         Exit Function
  15.     End If
  16.  
  17.  
  18.     DR = Format(vbaRound((D / V), 0), "#,##0")       'Formated Lowest Dilution Result
  19.         If DR = 0 Then
  20.             DR = 1
  21.         End If
  22.  
  23.     R = Format(vbaRound(((X * D) / V), 0), "#,##0") 'Formated Calculated Resul
  24.  
  25.     Select Case X
  26.         Case Is <= 0
  27.             cfuQBD = "<" & DR
  28.         Case Is > 0
  29.             If R <= 0.5 Then
  30.                 cfuQBD = "<" & DR
  31.             Else
  32.                 cfuQBD = R
  33.             End If
  34.     End Select
  35.  
  36. End Function
Where is the vbaRound function coming from? It isn't a vba defined function, so must be user defined somewhere. Could you post the code for it as well?

I suspect the discrepancy is caused by this rounding function.

Working on a copy of your database, try changing to simplify these two lines: DR = (D/V) And R = (X * D) / V)

Any time you are running high precision numbers through a rounding function, it will result in loss of accuracy.

Regards,
Scott
Sep 19 '07 #4
When I take out the rounding function (see below) R still equals 42222220.5444619 when X = 95, D = 10000 and V = 0.0225

I added Q to just run the numbers instead of the variables and I get 42222222.2222222.

Expand|Select|Wrap|Line Numbers
  1. Option Explicit
  2.  
  3. Public Function cfuQBD(X As Double, V As Double, D As Double) As String
  4.     'X is raw count
  5.     'V is volume
  6.     'D is dilution
  7.  
  8.     Dim R As Double   'Formated Calculated Result
  9.     Dim DR As Double  'Lowest Dilution Result
  10.     Dim Q As Double
  11.  
  12.     V = nz(V, 0)
  13.     D = nz(D, 1)
  14.  
  15.     If V = 0 Then
  16.         cfuQBD = vbNullString
  17.         Exit Function
  18.     End If
  19.  
  20.  
  21.     DR = Format(vbaRound((D / V), 0), "#,##0")       'Formated Lowest Dilution Result
  22.         If DR = 0 Then
  23.             DR = 1
  24.         End If
  25.  
  26.     'R = Format(vbaRound((X * D) / V), 0), "#,##0") 'Formated Calculated Result
  27.     R = X * D / V
  28.     Q = (CLng(95) * CLng(10000)) / 0.0225
  29.  
  30.  
  31.  
  32.     Select Case X
  33.         Case Is <= 0
  34.             cfuQBD = "<" & DR
  35.         Case Is > 0
  36.             If R <= 0.5 Then
  37.                 cfuQBD = "<" & DR
  38.             Else
  39.                 cfuQBD = R
  40.             End If
  41.     End Select

This is my vbaRound:

Expand|Select|Wrap|Line Numbers
  1. Option Compare Database
  2. Option Explicit
  3.  
  4. Public Enum rOpt
  5.     rNearest
  6.     rUp
  7.     rDown
  8. End Enum
  9.  
  10.  
  11.  
  12. Public Function vbaRound(dblValue As Double, intDecimals As Integer, _
  13.     Optional RoundingOption As rOpt = rNearest) As Double
  14.     Dim dblPlacesFactor As Double
  15.     Dim dlbRoundFactor As Double
  16.  
  17.     If intDecimals < 0 Then
  18.         vbaRound = 0
  19.         Exit Function
  20.     End If
  21.  
  22.     dblPlacesFactor = 10 ^ intDecimals
  23.  
  24.     Select Case RoundingOption
  25.     Case rNearest 'Round to Nearest
  26.         dlbRoundFactor = 0.5
  27.     Case rUp 'Round UP
  28.         dlbRoundFactor = 1
  29.     Case rDown 'Round DOWN
  30.         dlbRoundFactor = 0
  31.     End Select
  32.  
  33.     vbaRound = Int(dblValue * dblPlacesFactor + dlbRoundFactor) / dblPlacesFactor
  34. End Function
  35.  
  36. Public Function vbaRoundTO(dblValue As Double, dblRoundTo As Double, _
  37.     Optional RoundingOption As rOpt = rNearest) As Double
  38.     Dim dblRoundedMutliple As Double
  39.     Dim dblValueDiv As Double
  40.     Dim dblValueNew As Double
  41.  
  42.      'Set default retrun value if dblRoundTo = 0
  43.     If dblRoundTo = 0 Then
  44.         vbaRoundTO = 0 'OR vbaRoundTO = dblValue
  45.         Exit Function
  46.     End If
  47.  
  48.      'Find multiple of RoundToSmallest
  49.     dblValueDiv = dblValue / dblRoundTo
  50.  
  51.      'Option to RoundUP or RoundDOWN
  52.     Select Case RoundingOption
  53.     Case rNearest
  54.          'Round multiple to nearest
  55.          'DO NOT USE VBA Round() function.
  56.          'VBA : Round(2.5,0) = 2, i.e. rounds >=0.5 to 0 not 1
  57.         dblRoundedMutliple = vbaRound(dblValueDiv, 0)
  58.     Case rUp
  59.          'Round multiple UP
  60.         dblRoundedMutliple = vbaRound(dblValueDiv, 0, 1)
  61.     Case rDown
  62.          'Round multiple DOWN
  63.         dblRoundedMutliple = vbaRound(dblValueDiv, 0, 2)
  64.     Case Else
  65.     End Select
  66.  
  67.      'Calculate new "rounded-to" value
  68.     dblValueNew = dblRoundedMutliple * dblRoundTo
  69.  
  70.      'Return value
  71.     vbaRoundTO = dblValueNew
  72.  
  73. End Function
Sep 19 '07 #5
mlcampeau
296 Expert 100+
It definitely looks like a rounding problem because if you take
10000/.0225=444444.4444444444444444444444444....
Multiply that by 95 and you get your correct answer.
BUT
if you round it to 444444.4
Multiply that by 95, you get 42222218
or if you round it to 444444.44
Multiply that by 95, you get 42222221.8
I don't know enough VBA to help resolve this issue, but, it looks like it's the rounding that's causing it.
Sep 19 '07 #6
patjones
931 Expert 512MB
It definitely looks like a rounding problem because if you take
10000/.0225=444444.4444444444444444444444444....
Multiply that by 95 and you get your correct answer.
BUT
if you round it to 444444.4
Multiply that by 95, you get 42222218
or if you round it to 444444.44
Multiply that by 95, you get 42222221.8
I don't know enough VBA to help resolve this issue, but, it looks like it's the rounding that's causing it.
This is just a wild guess, but in other languages there is a big difference between 95 and 95.00 say. Even if you declare a variable as a double, I would explicitly put the placeholders in anyway as a matter of standard practice. Don't know if this makes a difference in VBA, but let me know!
Sep 19 '07 #7
The function runs twice per record. The first time R = 42222222.2222222 the second time R = 42222220.5444619.

Microsoft says:

"To optimize a query, Microsoft Access will not rerun a custom function unless the value passed to it changes. If the function accepts a field as a parameter, Microsoft Access must rerun the custom function for each record because the data may change from record to record. If criteria are placed on the result of the function, Microsoft Access must rerun the function when applying the criteria."

Any idea what is happening with the numbers the second time?

Debbie
Sep 19 '07 #8
Scott Price
1,384 Expert 1GB
When I take out the rounding function (see below) R still equals 42222220.5444619 when X = 95, D = 10000 and V = 0.0225

I added Q to just run the numbers instead of the variables and I get 42222222.2222222.

Expand|Select|Wrap|Line Numbers
  1. Option Explicit
  2.  
  3. Public Function cfuQBD(X As Double, V As Double, D As Double) As String
  4.     'X is raw count
  5.     'V is volume
  6.     'D is dilution
  7.  
  8.     Dim R As Double   'Formated Calculated Result
  9.     Dim DR As Double  'Lowest Dilution Result
  10.     Dim Q As Double
  11.  
  12.     V = nz(V, 0)
  13.     D = nz(D, 1)
  14.  
  15.     If V = 0 Then
  16.         cfuQBD = vbNullString
  17.         Exit Function
  18.     End If
  19.  
  20.  
  21.     DR = Format(vbaRound((D / V), 0), "#,##0")       'Formated Lowest Dilution Result
  22.         If DR = 0 Then
  23.             DR = 1
  24.         End If
  25.  
  26.     'R = Format(vbaRound((X * D) / V), 0), "#,##0") 'Formated Calculated Result
  27.     R = X * D / V
  28.     Q = (CLng(95) * CLng(10000)) / 0.0225
  29.  
  30.  
  31.  
  32.     Select Case X
  33.         Case Is <= 0
  34.             cfuQBD = "<" & DR
  35.         Case Is > 0
  36.             If R <= 0.5 Then
  37.                 cfuQBD = "<" & DR
  38.             Else
  39.                 cfuQBD = R
  40.             End If
  41.     End Select

This is my vbaRound:

Expand|Select|Wrap|Line Numbers
  1. Option Compare Database
  2. Option Explicit
  3.  
  4. Public Enum rOpt
  5.     rNearest
  6.     rUp
  7.     rDown
  8. End Enum
  9.  
  10.  
  11.  
  12. Public Function vbaRound(dblValue As Double, intDecimals As Integer, _
  13.     Optional RoundingOption As rOpt = rNearest) As Double
  14.     Dim dblPlacesFactor As Double
  15.     Dim dlbRoundFactor As Double
  16.  
  17.     If intDecimals < 0 Then
  18.         vbaRound = 0
  19.         Exit Function
  20.     End If
  21.  
  22.     dblPlacesFactor = 10 ^ intDecimals
  23.  
  24.     Select Case RoundingOption
  25.     Case rNearest 'Round to Nearest
  26.         dlbRoundFactor = 0.5
  27.     Case rUp 'Round UP
  28.         dlbRoundFactor = 1
  29.     Case rDown 'Round DOWN
  30.         dlbRoundFactor = 0
  31.     End Select
  32.  
  33.     vbaRound = Int(dblValue * dblPlacesFactor + dlbRoundFactor) / dblPlacesFactor
  34. End Function
  35.  
  36. Public Function vbaRoundTO(dblValue As Double, dblRoundTo As Double, _
  37.     Optional RoundingOption As rOpt = rNearest) As Double
  38.     Dim dblRoundedMutliple As Double
  39.     Dim dblValueDiv As Double
  40.     Dim dblValueNew As Double
  41.  
  42.      'Set default retrun value if dblRoundTo = 0
  43.     If dblRoundTo = 0 Then
  44.         vbaRoundTO = 0 'OR vbaRoundTO = dblValue
  45.         Exit Function
  46.     End If
  47.  
  48.      'Find multiple of RoundToSmallest
  49.     dblValueDiv = dblValue / dblRoundTo
  50.  
  51.      'Option to RoundUP or RoundDOWN
  52.     Select Case RoundingOption
  53.     Case rNearest
  54.          'Round multiple to nearest
  55.          'DO NOT USE VBA Round() function.
  56.          'VBA : Round(2.5,0) = 2, i.e. rounds >=0.5 to 0 not 1
  57.         dblRoundedMutliple = vbaRound(dblValueDiv, 0)
  58.     Case rUp
  59.          'Round multiple UP
  60.         dblRoundedMutliple = vbaRound(dblValueDiv, 0, 1)
  61.     Case rDown
  62.          'Round multiple DOWN
  63.         dblRoundedMutliple = vbaRound(dblValueDiv, 0, 2)
  64.     Case Else
  65.     End Select
  66.  
  67.      'Calculate new "rounded-to" value
  68.     dblValueNew = dblRoundedMutliple * dblRoundTo
  69.  
  70.      'Return value
  71.     vbaRoundTO = dblValueNew
  72.  
  73. End Function

Just as an interesting exercise I created a table field with type of Single. Plugged in the 0.0225 and then changed the data type to Double. The number then changed to: 0.0225000008940697

Running this number through the calculation results in 42222220.5444619. So what is apparently happening is that your rounding isn't happening soon enough, or isn't happening at all, causing Access/VBA to treat 0.0225 Single data type as 0.0225000008940697 Double data type throughout the calculation. I've got a meeting this afternoon, so won't be able to get back till this evening, but try refining your Rounding function using some Debug.Print's along the way to see where the number is being changed, and how to change (round) it back :-)

Regards,
Scott
Sep 19 '07 #9
mlcampeau
296 Expert 100+
Just as an interesting exercise I created a table field with type of Single. Plugged in the 0.0225 and then changed the data type to Double. The number then changed to: 0.0225000008940697

Running this number through the calculation results in 42222220.5444619. So what is apparently happening is that your rounding isn't happening soon enough, or isn't happening at all, causing Access/VBA to treat 0.0225 Single data type as 0.0225000008940697 Double data type throughout the calculation. I've got a meeting this afternoon, so won't be able to get back till this evening, but try refining your Rounding function using some Debug.Print's along the way to see where the number is being changed, and how to change (round) it back

Regards,
Scott


Your post didn't show up Scott so I hit reply and copied and pasted it....weird how it does that. It would only show up on mine after I took away the Quote blocks
Sep 19 '07 #10
Yeah! Thank you so much for you help. Yes that seems to be the problem and I can take it from here.

Thanks again,

Debbie
Sep 19 '07 #11
Scott Price
1,384 Expert 1GB
Thanks, mlcampeau! I've had it happen before, still not sure why...

Regards,
Scott
Sep 19 '07 #12
FishVal
2,653 Expert 2GB
Thanks, mlcampeau! I've had it happen before, still not sure why...

Regards,
Scott
It's likely you've quoted this huge post#5 in your reply. I've noticed this cause a post to be invisible.

Regards,
Fish.
Sep 19 '07 #13

Sign in to post your reply or Sign up for a free account.

Similar topics

8
by: Aspersion | last post by:
I'm building an ASP page that has a lot of text and graphics. There is a calculation facility on the page. The user enters several numbers in a form and presses a button to see the calculated...
0
by: anaxamandr | last post by:
Hi. I have a long loop in ASP that performs a rather lengthy calculation. I would love for my users to be able to stop that calculation, if they so choose, mid way through the process. I attempted...
2
by: Del | last post by:
Thanks in advance for any help. I have a database that was created in Access 2000. Several users have been upgraded to Access 2003. Since upgrading to 2003 we have noticed that some of the...
1
by: cdelaney | last post by:
I have a form that I created a calculation on using 2003. The calculation works exactly like I want it to but ONLY on the first and last record. The calculation does not work/exist on records in...
4
by: JK | last post by:
In my Windows form, I have a discrepancy between what the CrystaReport viewer displays and what the dataset contains. The Report displays data from three fields from same table but the...
4
by: Michiel Alsters | last post by:
Hello everybody, I hope anybody can help me. I'll try to give a brief overview of my problem. I have running a program that performs a heavy calculation. To give the user feedback what the...
4
by: vg-mail | last post by:
Hello all, I have identical design for form and report but I am getting calculation error on form and everything is OK on report. The form and report are build up on SQL statement. The...
5
by: The alMIGHTY N | last post by:
Hi all, Let's say I have a simple math formula: sum (x * y / 1000) / (sum z / 1000) I have to do this across 50 items, each with an x, y and z value, when the page first loads AND when a...
3
by: mattmao | last post by:
Okay, I was asked by a friend about the result of this limit: http://bbs.newwise.com/attdata/forumid_14/20070922_fe7f77c81050413a20fbDWYOGm7zeRj3.jpg Not n->zero but n-> + infinite I really...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.