I'm trying to solve "N Factor" of the following equation in VBA:
I have looked for other similar questions and I can't find any with suitable solutions.
I thought an iterative approach to obtain "N Factor" value from an initial value of N would work in VBA. For reference, the worksheet used is shown below:
When I try to do this programmatically in VBA incrementally from an initial value of N, it doesn't work. My code is below:
Function Fun_N(C, R, E, M, D As Double) As Double
With Application.WorksheetFunction
Dim D_Cal As Double
N = 0.001 'Arbitrary number to initialize the loop
D_Cal = ((1.5 * C) / ((4 * Atn(1)) * R)) * ((((0.0045 * E) ^ 3) / (N ^ 3)) * (1 - (1 / ((1 + (E / R) ^ 2) ^ 0.5))) + (1 / (M * ((1 + ((40000 * (N ^ 2)) / ((R ^ 2) * ((M) ^ (2 / 3))))) ^ 0.5)))) 'Constant Pi = 4 * Atn(1)
While D_Cal < D
N = N + 0.000001
D_Cal = ((1.5 * C) / ((4 * Atn(1)) * R)) * ((((0.0045 * E) ^ 3) / (N ^ 3)) * (1 - (1 / ((1 + (E / R) ^ 2) ^ 0.5))) + (1 / (M * ((1 + ((40000 * (N ^ 2)) / ((R ^ 2) * ((M) ^ (2 / 3))))) ^ 0.5)))) 'Constant Pi = 4 * Atn(1)
Wend
End With
Fun_N = N
End Function
I'm not know the issue (code, loop...)
Thanks in advance for help.
So I re-created your spread sheet and the first value I got for D-Cal was 13365959.6835436 using C = 9000, R = 6, E = 8, M = 3000, D = 0.115, N = 0.001 and copying the formulas as you had them. Your while loop will never execute as it says while D_Cal < D execute code. This is false at the start so the code inside the loop never executes. Changing this to:
While D_Cal > D
N = N + 0.000001
D_Cal = ((1.5 * C) / ((4 * Atn(1)) * R)) * ((((0.0045 * E) ^ 3) / (N ^ 3)) * (1 - (1 / ((1 + (E / R) ^ 2) ^ 0.5))) + (1 / (M * ((1 + ((40000 * (N ^ 2)) / ((R ^ 2) * ((M) ^ (2 / 3))))) ^ 0.5))))
Wend
Fun_N = N
gave me N = 0.946619000006383 as the answer so I think that is all you need to do.
Related
I'm getting divide by zero exceptions in this code of heron's method, and I am kind of lost here.
epsilon:: Integral a => a
epsilon = 1
heron:: Integral a => a -> a
heron r = help 0
where
help x
| abs (heron' x - heron' (x + 1)) < epsilon = heron' (x + 1)
| otherwise = help (x + 1)
heron' 0 = 1
heron' x = (1 `div` 2) * (heron' (x-1) + (r `div` heron' (x-1)))
Any suggestions where in this code I have to look to solve this problem?
(1 `div` 2) is definitely a problem , but what do I need to write instead?
If you need division of this kind, you probably want to use (/) instead of div and Fractional instead of Integral. So:
epsilon:: Fractional a => a
epsilon = 1
heron:: (Fractional a, Ord a) => a -> a
heron r = help 0
where
help x
| abs (heron' x - heron' (x + 1)) < epsilon = heron' (x + 1)
| otherwise = help (x + 1)
heron' 0 = 1
heron' x = (1 / 2) * (heron' (x-1) + (r / heron' (x-1)))
I need to plot a discrete signal that is defined by a piecewise function :
if n < 0 , x = (135/56) * (0.9)^n - (1/8)(0.1)^n - (2/7)(0.2)^n
if 0<=n< 4, x = (135/56) * (0.9)^n + (7/8)(0.1)^n + (5/7)(0.2)^n
if n>=4 , x = (135/56) * (0.9)^n + (7/8)(0.1)^n + (5/7)(0.2)^n + (0.1)^(-4) + (0.2)^(-4)
I have searched a lot in web and especially here and I came up with this code , that after many corrections it actually runned in spyder. But the result is definetely not the expected one. Can anyone help me?
import numpy as np
import matplotlib.pyplot as plt
xPoints = []
nPoints = []
q = (135 / 56)
z= -(1/8)
r = -(2/7)
m = 7/8
p = 5 /7
j = np.power(0.1, -3.5)
a = np.power(0.2, -3.5)
for n in range(-5,11):
if n<0 :
x = q *np.power(0.9, n) + z* np.power(0.1, n) + r* np.power(0.2, n)
elif (n>=0 and n<4):
x =q *np.power(0.9, n) + m* np.power(0.1, n) + p* np.power(0.2, n)
else:
x =q *np.power(0.9, n) + m* np.power(0.1, n) + p* np.power(0.2, n)+ j + a
xPoints.append(x)
nPoints.append(n)
plt.plot(nPoints, xPoints)
plt.plot.show()
In numpy stepwise functions can be created using where. One of numpy's most magical features is broadcasting, where a function can be called on a complete array of values at once.
Your example code creates the expected curve, but only adds a point at integer values. To create a smooth curve, np.linspace creates a long array of values (the code below uses 1000 little steps between -5 and 5). (Note that numpy needs the & operator for a logical and of two array expressions. In this particular case you could use n < 4 instead of (n >= 0) & (n < 4) as the case of n < 0 is taken care of earlier.)
import numpy as np
import matplotlib.pyplot as plt
q = (135 / 56)
z = -(1 / 8)
r = -(2 / 7)
m = 7 / 8
p = 5 / 7
j = np.power(0.1, -3.5)
a = np.power(0.2, -3.5)
n = np.linspace(-5, 5, 1000)
x = np.where(n < 0, q * np.power(0.9, n) + z * np.power(0.1, n) + r * np.power(0.2, n),
np.where((n >= 0) & (n < 4), q * np.power(0.9, n) + m * np.power(0.1, n) + p * np.power(0.2, n),
q * np.power(0.9, n) + m * np.power(0.1, n) + p * np.power(0.2, n) + j + a))
plt.plot(n, x)
plt.show()
If you only want the integer positions, you can use np.arange instead of np.linspace and then create a scatter plot (plt.scatter(n, x)) or maybe a stemplot:
import numpy as np
import matplotlib.pyplot as plt
q = (135 / 56)
z = -(1 / 8)
r = -(2 / 7)
m = 7 / 8
p = 5 / 7
j = np.power(0.1, -3.5)
a = np.power(0.2, -3.5)
n = np.arange(-5, 6)
x = np.where(n < 0, q * np.power(0.9, n) + z * np.power(0.1, n) + r * np.power(0.2, n),
np.where((n >= 0) & (n < 4), q * np.power(0.9, n) + m * np.power(0.1, n) + p * np.power(0.2, n),
q * np.power(0.9, n) + m * np.power(0.1, n) + p * np.power(0.2, n) + j + a))
plt.stem(n, x)
plt.show()
answer=0
for i in range (11):
k=i
x = (-1**k) / ((2 * k) + 1)
answer+=x
answer=4*answer
print(answer)
output: -8.723498311114408
it should be close to 3.14
** has precedence over - (see the docs), hence -1 ** k evalutes to -(1 ** k) which is of course not what you meant.
Change x = (-1 ** k) / ((2 * k) + 1) to x = (-1) ** k / ((2 * k) + 1)
I found out this snippet of code which works, but I do not understand why it does. It converts an Int to its representation in binary.
repBinario::Int -> Int
repBinario 0 = 0
repBinario x = 10 * repBinario (x `div` 2) + x `mod` 2
I know what div and mod do. However, how does it place each number that comes from mod together?
In short, it multiplies the accumulated result by 10 on each iteration.
To get a clearer understanding of what's going on we can divide your function into two simpler ones. The first one will convert an integer into a list of binary digits. The other will then do exactly the thing that bothers you: concat a list of binary digits into an integer.
extractBinDigits :: Int -> [Int]
extractBinDigits =
unfoldr (\x -> if x == 0 then Nothing else Just (mod x 2, div x 2))
concatDigits :: [Int] -> Int
concatDigits =
foldr (\a b -> a + b * 10) 0
As you see we simply fold the list multiplying the accumulator by 10 on each step and adding each digit to it.
Then your original function becomes just this:
repBinario :: Int -> Int
repBinario =
concatDigits . extractBinDigits
Division now lets us inspect and reuse the finer pieces of our program providing us with greater flexibility. E.g., by adding another simple function you can now convert the integer into a string in one go:
showDigits :: [Int] -> String
showDigits =
reverse . map (chr . (+ 48))
repStringyBinario :: Int -> String
repStringyBinario =
showDigits . extractBinDigits
Let’s go through an example, then:
repBinario 5
Substitute definition of repBinario 5:
10 * repBinario (5 `div` 2) + 5 `mod` 2
Reduce div and mod:
10 * repBinario 2 + 1
^
Here we have produced our first digit, marked with ^.
Substitute definition of repBinario 2:
10 * (10 * repBinario (2 `div` 2) + 2 `mod` 2) + 1
^
Reduce div and mod:
10 * (10 * repBinario 1 + 0) + 1
^ ^
Substitute definition of repBinario 1:
10 * (10 * (10 * repBinario (1 `div` 2) + 1 `mod` 2) + 0) + 1
^ ^
Reduce div and mod:
10 * (10 * (10 * repBinario 0 + 1) + 0) + 1
^ ^ ^
Substitute definition of repBinario 0:
10 * (10 * (10 * 0 + 1) + 0) + 1
^ ^ ^
Reduce:
101
At each step, (`mod` 2) gets the least significant binary digit, and (`div` 2) shifts the number rightward, discarding the digit and passing the rest of the number recursively to divBinario. At the end, we do the opposite process: (+ d) adds the current digit to the result, and (* 10) shifts the number leftward so we can add more digits.
What you get is a decimal number that looks identical to the binary representation of the original input.
If you remove the multiplication by 10, you get popCount, a function that gives you the population count of a number—the number of 1 bits in its binary representation:
popCount 0 = 0
popCount x = popCount (x `div` 2) + x `mod` 2
popCount 5 == 2
I think it would be best to calculate this function for a small value by hand - this is possible since this is a pure function therefore you can replace left hand side with its definition (i.e. right hand side) - the fancy computer science word for this feature is "referential transparency".
repBinario 24 = 10 * repBinario (24 `div` 2) + 24 `mod` 2
= 10 * repBinario 12 + 0
= 10 * (10 * repBinario (12 `div` 2) + 12 `mod` 2)
= 100 * repBinario 6 + 0
= 100 * (10 * repBinario (6 `div` 2) + 6 `mod` 2)
= 1000 * repBinario 3 + 0
= 1000 * (10 * repBinario (3 `div` 2) + 3 `mod` 2)
= 10000 * repBinario 1 + 1000 * 1
= 10000 (10 * repBinario (1 `div` 2) + 1 `mod` 2) + 1000
= 10000 (10 * repBinario 0 + 1) + 1000
= 10000 (10 * 0 + 1) + 1000
= 10000 * 1 + 1000
= 11000
in those steps I just evaluated the function by its definition and used the fact that integer-addition/multiplication obey the law of distribution.
I wrote a program which calculates the integral of the probability density function of the lognormal distribution.
I want it to be able to calculate the nth moments of the pdf too. But if I modify my code I get this error. It works properly before I add *(x^(M))
Function riemanint(n, a, b)
Dim h, i, x
h = (b - a) / n
x = a - h / 2
For i = 1 To n
x = x + h
s = s + f(x, ev, var, PI, M) * h
Next
riemanint = s
End Function
Function f(x, ev, var, PI, M)
PI = Application.WorksheetFunction.PI()
ev = Range("D2")
var = Range("E2")
M = Range("F2")
f = (((1 / (x * ((2 * PI) ^ 0.5) * var)) * Exp((-(Log(x) - ev) ^ 2) / (2 * var * var)))) * (x^(M))
End Function