I'm using VB.net 2013 and SQL server 2008R2.
I'm writing a financial application , and I'm not sure about which data type to use.
I know that decimal is more precise than float , but I read that using decimal can significantly decrease the speed of calculations , so the speed of my application.
I read that using decimals can be 20 times slower than using float.
Is this true , and if yes is there a solution or should I continue to use float ?
Thank you !
Use decimal for financial applications, period. Speed does not matter in this case. When money is lost, your users won't be happy. You cannot argue saying "well, but on the other hand, it was fast". Regarding 20 times difference on float vs decimal, trust me, you won't feel it at all, there will be more major factors in your app's performance. Most likely trying to synchronize transactions between each other, DB locks etc.
EDIT: Regarding 20 times performance difference, this is true, I was able to reproduce with below code:
Module Module1
Sub Main()
Dim f As Single = 123456792.0F
Dim fsw As New Stopwatch
fsw.Start()
For i = 1 To 100000000
f *= 1.00000012F
Next
fsw.Stop()
Dim dsw As New Stopwatch
dsw.Start()
Dim d As Decimal = 123456792.0F
For i = 1 To 100000000
d *= 1.00000012F
Next
dsw.Stop()
Console.WriteLine(f)
Console.WriteLine("Float (ms): " & fsw.ElapsedMilliseconds)
Console.WriteLine(d)
Console.WriteLine("Decimal (ms): " & dsw.ElapsedMilliseconds)
Console.WriteLine("Float is " & dsw.ElapsedMilliseconds / fsw.ElapsedMilliseconds & " faster")
Console.ReadLine()
End Sub
End Module
Output:
While writing this code, I got anywhere between 10-20 times for different numbers. As I mentioned before, speed is not the concern, compare the accuracy of both approaches, notice how float is off by several orders of magnitude. This is, of course, a synthetic example, but it shows how people may end up with 1 dollar on their payroll instead of a 1000 - imagine the reaction.
Related
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
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
I need to give a PWM output through a special output on my machine. I was just wondering how I could achieve something similar to thread.sleep but with the resolution of microseconds?
I am not sure why you want to rely on a so short period of time. You should bear in mind that the accuracy at these intervals is not too good and is even conditioned even by the CPU of the given machine. Thus, in any case you should thoroughly test the given approach under the given conditions to make sure that it delivers exactly what you want.
The smallest time value supported by .NET is a Tick (one hundred nanoseconds, as explained in this MSDN article) and thus you can build your own "sleep method" dealing with microseconds. Sample code:
Dim count As Integer = 0
Dim sw As Stopwatch = New Stopwatch
Dim microSeconds As Integer = 5
sw.Start()
Do While (sw.ElapsedTicks < 10 * microSeconds)
Loop
sw.Stop()
I have a requirement where in I need to sleep for a Poisson duration before sending the next packet. The current formula I can think of is
( e^(-lambda) X lambda^t ) / fact(t)
However, for time steps 280 and more the fact(t) would become obsolete due to overflow.
Can someone help me workaround this conventional way in VB .NET?
I think you are looking for the inter-arrival time. A random inter-arrival time can be generated using
t = (Math.log(1.0-Math.random())/-lambda
The formula you posted is the one that defines the probability that there are exactly t (in your case) arrivals within a specific time period.
See the Wikipedia article on generating Poisson distributions.
Even though the factorial value is getting extremely large (as you've observed), the λ k term is also getting somewhat large to compensate. For a way to represent the distribution that takes this into account, see the Wikipedia article on the Poisson distribution:
A VB implementation might look something like:
Module Module1
Sub Main()
Console.WriteLine(Poisson(4, 250))
Console.ReadKey()
End Sub
Function Poisson(ByVal lambda As Integer, ByVal k As Integer) As Double
Poisson = Math.Exp(k * Math.Log(lambda) - lambda - SumOverLn(1, k))
End Function
Function SumOverLn(ByVal start As Integer, ByVal endval As Integer) As Long
Dim i As Integer
SumOverLn = 0
For i = start To endval
SumOverLn = SumOverLn + Math.Log(i)
Next
End Function
End Module
It looks like after a while it is so close to 0 that it registers as such. You may be able to adjust the precision of the display to get more decimal places, but 0 might be a decent enough approximation for high values (the notion that you get from the probability theory seems to be that those values are indeed very close to zero anyway).
I am developing an application that is very very time critical. I want to put a log writer in the code so that i can track the events and find out where the application is wasting the time.But the problem is that vb.net tells the time only at a interval of 15.25 milliseconds what to do. although msdn documentation says that we can get the time in millisecond.
To understand my problem better pls go through the following code. this code is written on a click event of a button and it writes down the time in a log file.
the problem is that it writes time like 16,16,16 and after some time when the dx value reaches to say 5000 it jumps to 31 and then to 46 and so on. Can anyone explain.
dx = 1
While dx <= 100000
dx = dx + 1
SRLog1.WriteLine("dx vALUE > " & CStr(dx) & " Ticks -> " + CStr(Now.Millisecond))
End While
You can create an incremental clock with much higher resolution by using the Stopwatch class. For example:
Dim sw = Stopwatch.StartNew()
Dim start = sw.Elapsed
'' Do stuff
'' ...
Dim sample = sw.Elapsed
Console.WriteLine(sample - start)
This is still not likely to work out that well for the code in your snippet, incrementing an integer takes less than half a nanosecond. You'll actually measure how long it takes to log, that ought to be slow enough to get different output values.
If you want to find out which parts of your application are waisting time, then you should try using a profiler. Two possible products would be JetBrains dotTrace and RedGates ANTS. You should also take a look at this question here.