Why does Round produce a different result than Application.Round [duplicate] - vba

This question already has an answer here:
Round function in Excel, worksheet function vs VBA
(1 answer)
Closed 6 years ago.
I am finding that the VBA Round function returns the wrong result. I found a working alternative which is to use the Application.Round instead.
Why doesn't the VBA Round function work as expected?
Sub roundingResults()
Range("A1") = 123456.705
Debug.Print "Approach #1 " & Round(Range("A1").Value, 2)
Debug.Print "Approach #2 " & Application.Round(Range("A1").Value, 2)
End Sub
Output
Approach #1 123456.7
Approach #2 123456.71

There is no entirely correct answer for how to round. The differences have to do with how to handle values that fall exactly on the midpoint. Application.Round will always round up in that instance. e.g. 0.5 will round to 1.0. VBA.Round will tie break to the closest even number
1.5-->2
2.5-->2
3.5-->4
and so forth. This is one way of several ways of reducing the bias inherent in always rounding up.
Also, if interested, there is a fairly extensive discussion of Rounding in this Wikipedia article

Related

Fat fingered decimal entry VBA for excel [duplicate]

This question already has answers here:
Decimal TryParse in VBA
(2 answers)
Closed 4 years ago.
I made a simple vba application that allows a user to enter data into excel. The data that's being entered had to be >= 1.99 ohms and can be 3.00 or higher. Everything works great and it's been in use for over a year now. However, recently a user fat fingered a decimal point and didn't catch it until they entered the number. VBA didn't like that and errored out. The format they entered looked like so: '.2.34'. I can't seem to figure out how to avoid this. Any suggestions?
I've tried using:
If Res.value <> Format(Number, "#.##") Then
Msgbox ("blah blah")
Res.Value = ""
Exit Sub
End if
This blocks those entries, but it also blocks correct entries.
Maybe you could add Data Validation rules on the typical ranges. Try this: Data > Data Tools > Data Validation

VBA Division of integers

It seems improbable that this is not a duplicate of a question that already has an answer but I can't find that question or answer so here I go...
In VBA, in the immediate window, if I type:
?8/7
I get the result:
1.14285714285714 which if I then multiply by 7 gives me a number that is slightly LESS than 8, i.e. 7.99999999999998. My pocket calculator provides more decimal places, so it's better than VBA? Right? ;-)
However, if I add 0.000000000000003 to the RESULT 1.142... before I multiply I get 8 (which, by the way, is also incorrect); but my question is:
How can I control the precision of the answer with respect to the number of decimal places shown for ?8/7?
I have seen this answer relating to the accuracy of floating points but it is a different question, it explains the reasons for the inaccuracies whereas I am interested in getting a few extra digits.
To this end I have tried writing a function that returns a double but it does not return enough decimal places... for example I'd like to see: 1.142857142857142857. I also found references to a decimal data type but I think the article is for VB6 (instead of VBA) think I have exhausted the available data types in VBA... what am I missing?
Function test() As Double
Dim a As Double
Dim b As Double
Dim c As Double
a = 8
b = 7
c = a / b
test = c
End Function
Graphing and scientific calculators are not built for speed. They can afford to use software implementation of decimal floats for their calculations rather than IEEE doubles. So it is quite possible that your pocket calculator has greater precision than VBA, but at a cost. What they do is likely to be more than an order of magnitude slower.
VBA lacks a built-in arbitrary precision floating point library, but its decimal type supports higher precision than doubles. Unfortunately, it isn't a full-fledged data type but is rather a subtype of Variant. To create them, you need to use CDec():
Sub test()
Dim x As Variant
x = CDec(8) / 7
Debug.Print x
End Sub
This displays 1.1428571428571428571428571429
When using Decimal, you need to be aware of the fact that if you are not careful, they can pop back to e.g. a Double depending on how you use them:
Sub test2()
Dim x As Variant
x = CDec(x)
Debug.Print TypeName(x)
x = 8 / 7
Debug.Print x
Debug.Print TypeName(x)
End Sub
Output:
Decimal
1.14285714285714
Double

VBA Integer vs Long for counting tries on check if random number is equal to picked number at a range of 1 to 100

Last week I had to take a test in VBA. I had to code a little "game". These were the rules:
Pick a number between 1 and 100 (1 and 100 included)
Call function Randomize
Generate a random number between 1 and 100 (1 and 100 included) -> Int (100 * Rnd + 1)
Check if random number = chosen number.
5.1 If true, add +1 to counter, print counter, game is finished
5.2 If false, add+1 to counter, go back to Step 3.
I hope you get the aim of the "game".
I initialized the counter as an Integer (16 bit). My teacher told me that it is possible, that the counter might overflow. He recommends using a Long (32 bit) so that the chance to overflow is smaller.
I told him that it is nearly impossible to reach 32000 tries on the counter, because the chance that the picked number is equal to the generated number is 1:100.
He replied: But it's still possible.
My question:
Is it possible that the counter might overflow if the datatype is Integer? If yes, what's the chance? If no, how can I proof it?
Why is this question on stackoverflow and not on statistics?
It's simple. Because you guys know the Rnd-function and VBA behind the scenes, the guys on statistics don't.
Something like this I used in the past for file sampling, bringing the question is a Byte sufficient (1-255)?
Public dicGeneratedAlready As Scripting.Dictionary
Public Function GENERATE_RANDOM(intFromNumber As Integer) As Integer
Randomize
If dicGeneratedAlready Is Nothing Then Set dicGeneratedAlready = New Scripting.Dictionary
GenerateRand:
GENERATE_RANDOM = Int((Rnd * intFromNumber) + 1)
If dicGeneratedAlready.Exists(CStr(GENERATE_RANDOM)) Then
GoTo GenerateRand
Else
dicGeneratedAlready.Add CStr(GENERATE_RANDOM), CStr(GENERATE_RANDOM)
End If
End Function
From your description above there seems to be nothing stopping the code from trying numbers it has already tried before, so theoretically a long doesn't help, that could overflow as well, i.e. this could go on to infinity

IF Without End IF in VBA [duplicate]

This question already has answers here:
IF statements in VBA
(5 answers)
Closed 7 years ago.
see the code below.
IF Weight=0 Then CallFunction
IF Weight=100 Then
Heavy=True
Else
Heavy= False
End If
How is the program working when I have not ended a if statement?
its VBA's functionality to end up if statements in a single line..
If Weight is equal to zero, then CallFunction is executed (if Weight is not equal to zero, a CallFunction is not executed), then the code is going to another if statement. That's all! Debug the program to find out ;)

Avoiding overflow with large numbers when using Mod

I began toying with project euler.
I have completed problem #3, but I was only able to complete it by setting my endNumber to 71 * 486847 (manually calculated). When trying to set endNumber = 600851475143 I receive the overflow error.
I even set endNumber as Long, and even Double which I think should be plenty of digits to calculate.
I can't post the whole code here, so I'll post half in hopes someone can show me how to edit it in order to process larger numbers.
Also I noticed that "#" pops up when my code has a very large number like below.
endNumber = 600851475143#
countFactor = 0
For i = 2 To endNumber
If endNumber Mod i = 0 Then
The overflow isn't due to assigning the number 600851475143 to the Double variable it is that the Mod function does not seem to handle numbers longer than Long very well (in fact seemingly not at all).
An alternative can be to use the manual calc for Mod:
endNumber = 600851475143#
countFactor = 0
For i = 2 To endNumber
If endNumber - (Int(endNumber / i) * i) = 0 Then
If you are going to use Mod for large numbers on a regular basis then Chip Pearson's function would be a useful one (which is where I learnt about this subject matter in the first place). It is posted as a problem in Excel but works perfectly in Access.
The highest possible number to work with in a long is: 2.147.483.647
A Double is for decimal purposes, so thats not what you are looking for.
The # that pops up is because a number is to large to be shown inside that cell.
Also I don't know what you want to do with that loop. But that one is going to take a very long while to run.
on this link you can find about handling large numbers: Large Number Arithmetic
Hope that helps