Vb maths calculations incorrect results - vb.net

I am trying to calculate the expected "score" for a given player in an elo system*.
The problematic line of code is as follows:
expected(0) = (1 / (1 + (10 ^ (1000 - 1000) / 400)))
When I return the value of expected(0) directly after this line as a msgbox in a windows forms application, it states the value to be 11 even though it should be 1 (expected(1) is declared as an array of integers).
When I run this same line of code in a console application, it returns 1.
Is there any reason why this line of code is instead returning 11?
Edit: The exact code of the subroutines for both the console application that I tested (which returns correct value) and the forms application:
Forms:
Dim expected(1) As Integer
expected(0) = (1 / (1 + (10 ^ (1000 - 1000) / 400)))
Msgbox(expected(0))
Console:
Dim t(1) As Integer
t(0) = (1 / (1 + (10 ^ (1000 - 1000) / 400)))
Console.WriteLine(t(0))
Console.ReadLine()
The above numeric values (e.g. 400, 1000) are literally written in to the program like that, as I was just testing whether they work.
*you can look up the equation on the wikipedia page "Elo rating system" but I don't think it is important in this situation. In this situation I am simulating both players Elo being 1000.

Apologies to anyone who was scratching their head at this, but the solution was very simple and the problem was 100% my fault. As it turns out msgbox(expected(0) was actually written as msgbox("expected 1" & expected(0)) which came out in the box as "expected 11" rather than "1" or "expected 1 1". I thought 11 was the value. Apologies again.

Your formula from Wikipidia is:
One way to code this accurately:
Dim d1 As Double = (Rb - Ra) / 400R '0
Dim d2 As Double = 1 + System.Math.Pow(10, d1) '2
Dim EA As Double = 1 / d2 '0.5
Your expression:
(1 / (1 + (10 ^ (1000 - 1000) / 400)))
Is not an accurate translation of the source forumul above, your expression above returns zero instead of 0.5. If EA is an integer, value you will get the same result from both calculations, but I think you should always get the correct value then explicitly manipulate it rather manipulating it implicitly (by the compiler, for instance).

Related

How to see what the is being compared in a if statement

I'm having a problem with some vba code.
I have a if statement that doesn't treat the same content equally.
e.g: 0,1 equals 0,1, but a re-run 0,1 does not equal 0,1
(this values are shown by MVBA)
The code is long so before posting it i would like to know if it's possible to see the machine perspective in a if statement (hex, ascii...). This because, although the debug is telling me they are the same (through msgbox, vartype, etc), the if statement is not activated.
pseudo code:
x = 0,0000001 * 1*10^6 (which equals 0,1)
y = 0,0001 * 1*10^3 (which also equals 0,1)
if statement:
x doesn't enter
y does
end if
This is because the floating-point implementation may not be able to represent those number accurately due to the fact that they are encoded in a base 2 representation.
If you want to compare them, I would suggest using Cdec (wich converts to Decimal, a VBA custom base 10 floating-point)
Debug.Print (0.0000001 * 1 * 10 ^ 6) = (0.0001 * 1 * 10 ^ 3) ' False
Debug.Print CDec(0.0000001 * 1 * 10 ^ 6) = CDec(0.0001 * 1 * 10 ^ 3) ' True
While they both display 0.1, in fact 0.0000001 * 1 * 10 ^ 6 flaoting-point value is 0x3FB9999999999999 whereas 0.0001 * 1 * 10 ^ 3 returns 0x3FB999999999999A.
I'd recommend reading What Every Computer Scientist Should Know About Floating-Point Arithmetic

type-declaration character does not match declared data type

I keep getting this compile error based on the code below and I cannot figure it out for the life of me. Can you guys see what the problem is? It highlights the "p" when I go back to debug.
Thanks,
R
Function EuroBin(S, K, T, rF, sigma, n, PutCall As String)
dt = T / n: u = Exp(sigma * Sqr(dt))
d = 1 / u: p = (Exp(rF * dt) - d) / (u - d)
EuroBin = 0
For i = 0 To n
Select Case PutCall
Case "Call":
EuroBin = WorksheetFunction.Combin(n, i) * EuroBin + p^(i) * (1 - p) ^ (n - i) * WorksheetFunction.Max(S * u^(i) * d^(n - i) - K, 0)
Case "Put":
EuroBin = WorksheetFunction.Combin(n, i) * EuroBin + p^(i) * (1 - p) ^ (n - i) * WorksheetFunction.Max(K - S * u^(i) * d^(n - i), 0)
End Select
Next i
EuroBin = Exp(-rF * T) * EuroBin
End Function
For exponentiation, use
WorksheetFunction.Power(b, e)
instead of b^e, which seems to not work in VBA!
I'm saying that based on the test Debug.Print 2^2, which returns 2 2; Debug.Print WorksheetFunction.Power(2, 2) returns 4.
Exponentiation works like you expect when you use the caret ^ in 32-bit Excel VBA. It fails to work as expected only in 64-bit Excel VBA.
In 64-bit Excel VBA, the caret is the type declaration character for the LongLong variable type. So when you enter a number followed by a caret or a variable name followed by the caret, VBA assumes you are talking about a LongLong constant or variable. Having made that assumption, it then tries to parse the expression and will give you either a run-time error or an unexpected result.
If you surround your constant or variable in parentheses like (a)^b or (2)^3, you may then use the caret to perform exponentiation in 64-bit Excel VBA. That is my recommended practice as it works as expected in 32-bit Excel VBA, too.
You may also notice that doubling the caret appears to exponentiate correctly--but that is only true for whole numbers. The first caret converts your whole number into a LongLong, while the second one performs the exponentiation. But you can't count on this behavior in general, because 2.3^^3 will raise a run-time error (because 2.3 can't be a LongLong). And if your code is used in both 32-bit and 64-bit Excel, doubling the caret will produce a run-time error in 32-bit Excel. For these reasons, I recommend against the practice of doubling the caret.

Strange result of floating-point operation

Problems like this drive me crazy. Here's the relevant piece of code:
Dim RES As New Size(Math.Floor(Math.Round(mPageSize.Width - mMargins.Left - mMargins.Right - mLabelSize.Width, 4) / (mLabelSize.Width + mSpacing.Width) + 1),
Math.Floor((mPageSize.Height - mMargins.Top - mMargins.Bottom - mLabelSize.Height) / (mLabelSize.Height + mSpacing.Height)) + 1)
Values of the variables (all are of Single type):
mPageSize.Width = 8.5
mMargins.Left = 0.18
mMargins.Right = 0.18
mLabelSize.Width = 4.0
mSpacing.Width = 0.14
For God-knows-what reason, RES evaluates to {Width=1,Height=5} instead of {Width=2,Height=5}. I have evaluated the expressions on the right-side individually and as a whole and they correctly evaluate to {2,5}, but RES would never get correct value. Wonder what am I missing here.
EDIT
I have simplified the problem further. The following code will produce 2.0 if you QuickWatch the RHS, but the variable on the LHS will get 1.0 after you execute this line:
Dim X = Math.Floor(Math.Round(mPageSize.Width - mMargins.Left - mMargins.Right - mLabelSize.Width, 4) / (mLabelSize.Width + mSpacing.Width) + 1)
Time for MS to check it out?
EDIT 2
More info. The following gives correct results:
Dim Temp = mPageSize.Width - mMargins.Left - mMargins.Right - mLabelSize.Width
Dim X = Math.Floor(Temp / CDec(mLabelSize.Width + mSpacing.Width)) + 1
The problem is that the following expression evaluates to a value just below 1:
Math.Round(mPageSize.Width - mMargins.Left - mMargins.Right - mLabelSize.Width, 4) / (mLabelSize.Width + mSpacing.Width)
= 0.99999999985602739 (Double)
But what's the reason for that? The truth is that I don't know exactly. The MSDN does not offer enough information about the implementation of / but here's my guess:
Math.Round returns a Double with value 4.14. The right-hand side of the division is a Single. So you're dividing a Double by a Single. This results in a Double (see MSDN). So far, so good. The MSDN states that all integral data types are widened to Double before the division. Although Single is not an integral data type, this is probably what happens. And here is the problem. The widening does not seem to be performed on the result of the addition, but on its operands.
If you write
Dim sum = (mLabelSize.Width + mSpacing.Width) 'will be 4.14 Single
Math.Round(mPageSize.Width - mMargins.Left - mMargins.Right - mLabelSize.Width, 4) / sum
= 1 (Double)
Here sum is converted to double (resulting in 4.14) and everything is fine. But, if we convert both operands to double, then the conversion of 0.14 introduces some floating point error:
Dim dblLabelSizeWidth As Double = mLabelSize.Width ' will be 4.0
Dim dblSpacing As Double = mSpacing.Width ' will be 0.14000000059604645
The sum is slightly bigger than 4.14, resulting in a quotient slightly smaller than 1.
So the reason is that the conversion to double is not performed on the division's operand, but on the operand's operands, which introduces floating point errors.
You could overcome this problem by adding a small epsilon to the quotient before rounding off. Alternatively you might consider using a more precise data type such as Decimal. But at some point, there will also be floating-point errors with Decimal.
This is due to rounding error: you're taking the floor of a value that is very close to 2, but is less than 2 (while the mathematical value is 2). You should do all your computations with integers, or take rounding errors into account before using operations like floor (not always possible if you want the true value).
EDIT: Since vb.net has a Decimal datatype, you can also use it instead of integers. It may help in some cases like here: the base conversions for 0.18 and 0.14 (not representable exactly in binary) are avoided and the additions and subtractions will be performed exactly here, so that the operands of the division will be computed exactly. Thus, if the result of the division is an integer, you'll get it exactly (instead of possibly a value just below, like what you got with binary). But make sure that your inputs are already in decimal.

vb.net cube root gives wrong value?

I was simply looking for a way to get cube roots in vb.net. The consensus online is to use the formula:
<number> ^ (1 / 3)
I tried punching a few of these into the immediate window and here's what I get:
?1 ^ (1 / 3)
1.0
?8 ^ (1 / 3)
2.0
?27 ^ (1 / 3)
3.0
?64 ^ (1 / 3)
3.9999999999999996
Wait a minute.. Shouldn't the answer be 4.0? What happened? 4 * 4 * 4 = 64, not 3.9999999999999996 * 3.9999999999999996 * 3.9999999999999996 = 64. I'm usually good with math problems but I've spent too much time with this and I could use some help. I'm not as interested in finding out why this failed as much as I am interested in how to make this work given the number 64 and trying to get the cube root to equal 4.
This works for me:
Private Function CubedRoot(ByVal dNum As Double) As Double
Return CType(CType(dNum ^ (1 / 3), Decimal), Double)
End Function

Smooth Coloring Mandelbrot Set Without Complex Number Library

I've coded a basic Mandelbrot explorer in C#, but I have those horrible bands of color, and it's all greyscale.
I have the equation for smooth coloring:
mu = N + 1 - log (log |Z(N)|) / log 2
Where N is the escape count, and |Z(N)| is the modulus of the complex number after the value has escaped, it's this value which I'm unsure of.
My code is based off the pseudo code given on the wikipedia page: http://en.wikipedia.org/wiki/Mandelbrot_set#For_programmers
The complex number is represented by the real values x and y, using this method, how would I calculate the value of |Z(N)| ?
|Z(N)| means the distance to the origin, so you can calculate it via sqrt(x*x + y*y).
If you run into an error with the logarithm: Check the iterations before. If it's part of the Mandelbrot set (iteration = max_iteration), the first logarithm will result 0 and the second will raise an error.
So just add this snippet instead of your old return code. .
if (i < iterations)
{
return i + 1 - Math.Log(Math.Log(Math.Sqrt(x * x + y * y))) / Math.Log(2);
}
return i;
Later, you should divide i by the max_iterations and multiply it with 255. This will give you a nice rgb-value.