Combines multiple recursive generator vba [duplicate] - excel

I have run into an overflow error in Excel VBA and cannot find my way around it. While Microsoft's documentation indicates that the range for doubles should reach ~1.8E308, I am receiving an overflow error for numbers significantly lower than that threshold. My code is as follows:
Public Function Fixed_Sample_Nums(ByVal n As Long, seed As Long) As Double()
Dim x() As Double, y() As Double, i As Long
ReDim y(1 To n)
ReDim x(1 To n)
x(1) = (CDbl(48271) * seed) Mod CDbl(2 ^ 31 - 1)
For i = 2 To n
x(i) = (CDbl(48271) * CDbl(x(i - 1))) Mod (CDbl(2 ^ 31 - 1))
y(i) = CDbl(x(i)) / CDbl(2 ^ 31 - 1)
Next i
Fixed_Sample_Nums = y
End Function
'I receive the error in the first iteration of the for loop with
'seed equal to any value >= 1 (i.e. w/ seed = 1):
Debug.Print((CDbl(48271) * CDbl(48271)) Mod (CDbl(2 ^ 31 - 1)))
'results in an overflow error
I am attempting to create a pseudo-random number generator that can take in any 'seed' value up to and including 2 ^ 31 - 1. The for loop should be able to iterate at least 9,999 times (i.e. n = 10000). If the overflow error is not encountered within the first few iterations, it most likely will not be encountered for any subsequent iteration.
As you can see, I am converting each integer to a double before any calculation. I am aware of the fact that arrays substantially increase the byte size of the calculation, but that does not appear to be the current issue as I directly copied the example calculation above into the immediate window and still received the overflow error. My attempts to find a solution online have resulted in no avail, so I would really appreciate any input. Thanks in advance!

Try using Chip Pearson's XMod function:
x(i) = XMod((CDbl(48271) * seed), CDbl(2 ^ 31 - 1))
As he notes:
You can also get overflow errors in VBA using the Mod operator with
very large numbers. For example,
Dim Number As Double
Dim Divisor As Double
Dim Result As Double
Number = 2 ^ 31
Divisor = 7
Result = Number Mod Divisor ' Overflow error here.
Code for the function:
Function XMod(ByVal Number As Double, ByVal Divisor As Double) As Double
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' XMod
' Performs the same function as Mod but will not overflow
' with very large numbers. Both Mod and integer division ( \ )
' will overflow with very large numbers. XMod will not.
' Existing code like:
' Result = Number Mod Divisor
' should be changed to:
' Result = XMod(Number, Divisor)
' Input values that are not integers are truncated to integers. Negative
' numbers are converted to postive numbers.
' This can be used in VBA code and can be called directly from
' a worksheet cell.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Number = Int(Abs(Number))
Divisor = Int(Abs(Divisor))
XMod = Number - (Int(Number / Divisor) * Divisor)
End Function
Additional details:
http://www.cpearson.com/excel/ModFunction.aspx

Related

Using a FOR loop within an Excel VBA Function

I created a simple function in MATLAB, and am trying to convert the function into Excel VBA function. My goal is to create an Excel formula =RT('range of dB levels', 'delta-time') and output the estimated reverberation time. The math is simple, see MATLAB code below:
function rr=RT(lvl_broad, dt)
n=12; %number of samples within slope calc
slope=zeros(length(lvl_broad), 1);
for i=1:length(lvl_broad)
if i<((n/2)+1) | i>length(lvl_broad)-(n/2)-1
slope(i)=0;
else
slope(i)=(lvl_broad(i+(n/2))-lvl_broad(i-(n/2)))/n;
end
end
min_slope=min(slope);
rr=abs(dt./min_slope)*60;
end
In excel, I modified/simplified this until I no longer got errors, however, the cell that I enter my 'RT' function in returns #VALUE and I do not know why. Does anything stand out in the code below? (note I changed the input range from lvl_broad to InterruptedNZ)
Function RT(InterruptedNZ, dt)
Dim Slope As Double
Slope = Slope(InterruptedNZ.Height, 1)
For i = 1 To InterruptedNZ.Height
If i < ((6) + 1) Or i > (InterruptedNZ.Height - (6) - 1) Then
Slope(i) = 0
Else
Slope(i) = (InterruptedNZ(i + (6)) - InterruptedNZ(i - (6))) / 12
End If
Next
End
min_slope = Application.WorksheetFunction.Min(Slope)
RT = Abs((dt / min_slope) * 60)
End Function
Here are some tips to translate MATLAB code into VBA code:
length()
If you are trying to get the dimensions of a range, you'll need to use the .Rows.Count or .Columns.Count properties on the range you are working with.
PERFORMANCE NOTE:
When you have a large enough range, it's a good idea to store the values of the range inside an array since you will reduce the number of times you access data from the sheets which can comme with lot of overhead. If so, you'll have to use ubound() and lbound().
zeros()
In VBA, there is no exact equivalent to the zeros() function in MATLAB. The way we would initialize an array of zeros would simply be by initializing an array of doubles (or another numerical type). And since the default value of a double is zero, we don't need to do anything else :
Dim Slope() As Double
ReDim Slope(1 To InterruptedNZ.Rows.Count)
Note that you cannot pass the dimensions in the Dim statement since it only accepts constants as arguments, so we need to create Slope as a dynamic array of doubles and then redimension it to the desired size.
Putting these two principles together, it seems like your code would look something like this:
Function RT(ByRef InterruptedNZ As Range, ByVal dt As Double)
Dim Slope() As Double
ReDim Slope(1 To InterruptedNZ.Rows.Count)
Dim i As Long
For i = 1 To InterruptedNZ.Rows.Count
If i < ((6) + 1) Or i > (InterruptedNZ.Rows.Count - (6) - 1) Then
Slope(i) = 0
Else
Slope(i) = (InterruptedNZ(i + (6)) - InterruptedNZ(i - (6))) / 12
End If
Next
Dim min_slope As Double
min_slope = Application.WorksheetFunction.Min(Slope)
RT = Abs((dt / min_slope) * 60)
End Function
Addtionnal notes:
Refering to cells from a range like this InterruptedNZ(i) works but it is good practice to be more specific like this (assuming column range) :
InterruptedNZ.Cells(i,1)
During my tests, I had a division by zero error since min_slope was zero. You might want to account for that in your code.

Overflowing Binary to Decimal Function

When I send in the string 1111101110001110 as the binary form of the number that I want, I get an
Error Overflow
in the code. Which in decimal would be 64398. I am returning it to an integer in the main function. This number should be small enough as to not overflow the integer right? Any help would be greatly appreciated.
Function Bin2Dec(ByVal Binarystring As String) As Integer ' This converts a binary to a decimal
Dim X As Integer
For X = 0 To Len(Binarystring) - 1
Bin2Dec = CDec(Bin2Dec) + Val(Mid(Binarystring, _
Len(Binarystring) - X, 1)) * 2 ^ X
Next
End Function

Access VBA to Excel, add apostrophe [duplicate]

Having a problem with this Error. I am creating a GA and the loop is to assign my fitness value to an array.
some of the variables
Dim Chromolength as integer
Chromolength = varchromolength * aVariables
Dim i as integer, j as integer, counter as integer
Dim Poparr() As Integer
Dim FitValarr() As Integer
the code:
ReDim Poparr(1 To PopSize, 1 To Chromolength)
For i = 1 To PopSize
For j = 1 To Chromolength
If Rnd < 0.5 Then
Poparr(i, j) = 0
Else
Poparr(i, j) = 1
End If
Next j
Next i
For i = 1 To PopSize
j = 1
counter = Chromolength
Do While counter > 0
FitValarr(i) = FitValarr(i) + Poparr(i, counter) * 2 ^ (j - 1)
j = j + 1
counter = counter - 1
Loop
Next i
I am having problems with:
FitValarr(i) = FitValarr(i) + Poparr(i, counter) * 2 ^ (j - 1)
I apologize, I am fairly new to VBA.
An overflow condition arises when you create an integer expression that evaluates to a value larger than can be expressed in a 16-bit signed integer. Given the expression, either the contents of FitValarr(i), or the expression 2^(j-1) could be overflowing. Suggest all the the variables presently declared as Int be changed to Long. Long integers are 32-bit signed values and provide a correspondingly larger range of possible values.
I had the same run time error 6. After much investigation l discovered that mine was a simple 'divide by zero' error.
I set up an integer value to hold Zip codes, and Error 6 events plagued me - until I realized that a zip code of 85338 exceeded the capacity of an int...
While I didn't think of a zip code as a "value" it was nonetheless certainly interpreted as one. I suspect the same could happen with addresses as well as other "non-numeric" numeric values. Changing the variable to a string resolved the problem.
It just didn't occur to me that a zip code was a "numeric value." Lesson learned.

Overflow Error in Excel VBA with Type Double

I have run into an overflow error in Excel VBA and cannot find my way around it. While Microsoft's documentation indicates that the range for doubles should reach ~1.8E308, I am receiving an overflow error for numbers significantly lower than that threshold. My code is as follows:
Public Function Fixed_Sample_Nums(ByVal n As Long, seed As Long) As Double()
Dim x() As Double, y() As Double, i As Long
ReDim y(1 To n)
ReDim x(1 To n)
x(1) = (CDbl(48271) * seed) Mod CDbl(2 ^ 31 - 1)
For i = 2 To n
x(i) = (CDbl(48271) * CDbl(x(i - 1))) Mod (CDbl(2 ^ 31 - 1))
y(i) = CDbl(x(i)) / CDbl(2 ^ 31 - 1)
Next i
Fixed_Sample_Nums = y
End Function
'I receive the error in the first iteration of the for loop with
'seed equal to any value >= 1 (i.e. w/ seed = 1):
Debug.Print((CDbl(48271) * CDbl(48271)) Mod (CDbl(2 ^ 31 - 1)))
'results in an overflow error
I am attempting to create a pseudo-random number generator that can take in any 'seed' value up to and including 2 ^ 31 - 1. The for loop should be able to iterate at least 9,999 times (i.e. n = 10000). If the overflow error is not encountered within the first few iterations, it most likely will not be encountered for any subsequent iteration.
As you can see, I am converting each integer to a double before any calculation. I am aware of the fact that arrays substantially increase the byte size of the calculation, but that does not appear to be the current issue as I directly copied the example calculation above into the immediate window and still received the overflow error. My attempts to find a solution online have resulted in no avail, so I would really appreciate any input. Thanks in advance!
Try using Chip Pearson's XMod function:
x(i) = XMod((CDbl(48271) * seed), CDbl(2 ^ 31 - 1))
As he notes:
You can also get overflow errors in VBA using the Mod operator with
very large numbers. For example,
Dim Number As Double
Dim Divisor As Double
Dim Result As Double
Number = 2 ^ 31
Divisor = 7
Result = Number Mod Divisor ' Overflow error here.
Code for the function:
Function XMod(ByVal Number As Double, ByVal Divisor As Double) As Double
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' XMod
' Performs the same function as Mod but will not overflow
' with very large numbers. Both Mod and integer division ( \ )
' will overflow with very large numbers. XMod will not.
' Existing code like:
' Result = Number Mod Divisor
' should be changed to:
' Result = XMod(Number, Divisor)
' Input values that are not integers are truncated to integers. Negative
' numbers are converted to postive numbers.
' This can be used in VBA code and can be called directly from
' a worksheet cell.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Number = Int(Abs(Number))
Divisor = Int(Abs(Divisor))
XMod = Number - (Int(Number / Divisor) * Divisor)
End Function
Additional details:
http://www.cpearson.com/excel/ModFunction.aspx

Overflow error with Mod in VBA when value is in the billions or greater

I am trying to find the largest prime divisor of a number x. When x is smaller than 1billion my code works but when it is greater than 1billion it gives an overflow error and debugging highlights the line with Mod in it.
Sub Largest_Divisor()
Dim x As Double
Dim Q As Integer
Q = 0
Dim L() As Double
x = 999999999#
Dim i As Double
For i = 775145 To 3 Step -2
If x Mod i = 0 Then
If IsPrime(i) Then
ReDim Preserve L(Q) As Double
L(Q) = i
Q = Q + 1
End If
End If
Next i
MsgBox (Application.Max(L))
End Sub
I suspect it is when x is larger than about 2 billion, 2,147,483,648 to be precise, that you have trouble.
That is because as per the documentation of mod, at most a long is returned, which ranges in value from -2,147,483,648 to 2,147,483,647 as a 32-bit signed value. It is not explicitly stated in the help documentation, but the arguments of mod are probably coerced to long as well.
A good work around can be to use this function:
Function Modulus(int1 As Double, int2 As Double) As Double
' This function will return int1 Mod int2. It is useful when |int1| exceeds
' 2,147,483,647 as the VBA Mod function will then break.
'
Dim myInt As Integer
myInt = Int(int1 / int2)
Modulus = int1 - (myInt * int2)
Return Modulus
End Function

Resources