We've been trying to implement a new number that can be any amount of bytes because we need a lot of precision during calculation. As well as that we're working in Unity Burst which at the moment does not support anything bigger then a float.
We've been doing this by using a byte array and implementing binary addition, subtraction, multiplication and division. And this is partly working.
The problem we're walking into is that the performance is way slower then the integer math.
So it will produce the following:
4*3 run 100.000 with int's will take about 0-1 milliseconds
4*3 run 100.000 with our number will take about 100 milliseconds
So the question is if we could use the same kind of implementation by inheriting or copying the integer math code. Or even just get a look at how it's implemented? I looked in the C# source code but can't quite find the actual math.
Any help or ideas would be appreciated.
As Tim Rutter suggested in the comments, take a look at the BigInteger class in .NET docs.
It isn't supported in the old Mono c# 2.0, but it is supported since .NET 4x in Unity 2017.1
To use it with burst compiler, you can convert the BigInteger instance to a byte array, as shown here.. I guess it would be similar to your workflow, except that you have to convert it back to BigInteger when making calculations.
If that doesn't work, I suggest taking a look at the first answer here, as it provides a solution for a custom BigInteger class (I haven't tried or tested it)
Related
I have two questions regarding implementation of Random class in .NET Framework 4.6 (code available here):
What is the rationale for setting Seed argument to 1 at the end of the constructor? It seems to be copy-pasted from Numerical Recipes in C (2nd Ed.) where it made some sense, but it doesn't have any in C#.
It is directly stated in the book (Numerical Recipes in C (2nd Ed.)) that inextp field is set to value 31 because:
The constant 31 is special; see Knuth.
However, in the .NET implementation this field is set to value 21. Why? The rest of a code seems to closely follow the code from book except for this detail.
Regarding the intexp issue, this is a bug, one which Microsoft has acknowledged and refused to fix due to backwards compatibility concerns.
Indeed, you have discovered a genuine problem with the Random implementation.
We have discussed it within the team and with some of our partners and concluded that we unfortunately cannot fix the problem right now. The reason is that some applications rely on the fact that when initialised with the same seed, the generator produces the same pseudo random sequence. Even if the change is for the better, it will break the applications that made this assumption once they have migrated to the “fixed” version.
For some more context:
A while back I fully analysed this implementation. I found a few differences.
A the first one (perfectly fine) is a different large value (MBIG). Numerical Recipies claims that Knuth makes it clear that any large value should work, so that is not an issue, and Microsoft reasonably chose to use the largest value of a 32 bit integer.
The second one was that constant, you mentioned. That one is a big deal. In the minimum it will substantially decrease period. There have been reports that the effects are actually worse than that.
But then comes one other particularly nasty difference. It is literally guarenteed to bias the output (since it does so directly), and will also likely affect the period of the RNG.
So what is this second issue? When .NET first came out, Microsoft did not realize that the RNG they coded was inclusive at both ends, and they documented it as exclusive at the maximum end. To fix this, the security team added a rather evil line of code: if (retVal == MBIG) retVal--;. This is very unfortunately as the correct fix would literally be only 4 added characters (plus whitespace).
The correct fix would have been to change MBIG to int.MaxValue-1, but switch Sample() to use MBIG+1 (i.e. to keep using int.MaxValue). That would guarantee the that Sample has the range [0.0, 1.0) without introducing any bias, and only changes the value of MBIG which Numerical Recipies said Knuth said is perfectly fine.
I asked this question a while ago on math.stackexchange.
I was given the formula for the pdf of a skewed normal distribution but it involves integrals and I have no clue how to implement the formula in C#.
Like I said in the question linked, I'm writing a program where certain 'effects' are strong in the beginning and weaker later on or vice-versa. I've opted to use a skewed standard distribution.
I just want a formula where I input the skewness, 'x' and get the density for that particular x on the graph.
If I can understand how to implement the formula he gave perhaps I can also use it for non-standard distributions where the mean and standard deviation are something other than 0 and 1 respectively.
I checked out Math.NET but was unable to find something that could help me here. I have no clue where to start.
There are a number of ways to numerically solve integrals, with a few methods being more popular than others. A simple google search for "numerically solve integrals" will probably be more beneficial than a solitary answer here.
If you're looking for an example specifically in c#, this link will provide implementation in c# for a definite integral for the mid-point, simpson, and trapezoidal methods to solutions.
The integral mentioned in flawr's answer to your question is, as he/she says, the cdf of the normal distribution. There is a simple formula for that, namely Phi(x) = 1/2 (1 + erf(x/sqrt(2))), where erf is the Gaussian error function, which is commonly included in math libraries; I don't know about .Net in particular.
You don't have to compute the integral numerically; just find erf in some library. In fact, computing the integral numerically is almost certainly going to be less accurate than using erf from a library, and it will certainly be more work.
EDIT: Answers for this SO question seem to suggest that this implementation of erf for C# is useful.
Ive found simlar posts before about this but nothing really answers the question.
In my fingerprinting, i produce a recordset which has 5 integers. For example:
33,42,88,121,194
These correspond to the frequencies which have the highest magnitude for a particular sample of music.
Eg: for 30ms of audio sample i have buckets of the following frequencies:
0-40
40-80
80-120
120-180
180-250
Im trying to produce a hash (a forgiving one) which will perhaps produce the same hash for
33,42,88,121,194 as it would for say
33,43,88,122,195
where there are minor differences in the frequencies a similar hash would be formed.
1st off is this LSH? as i have read that this is best for Audio Fingerprinting.
If not, could anyone provide some psuedocode or c# for a function that might do what im looking for? i have read up on LSH and matlab and perl implementations but i dont understand them so posting a link to them won't really help me too much.
thanks again!
This might be a duplicate of this: Compare two spectogram to find the offset where they match algorithm, what it appears you are trying to do is produce a histogram for the rough distribution of the peaks in the sample. There are several methods to do this, another "example" is here: Compare two spectogram to find the offset where they match algorithm
One method of doing this is to use a Fast-Fourier-Transform of the peak data and its distribution (over time) to produce a rough equivalence of the sample in a distilled form. To do this you do something roughly similar to:
Divide the sample into some discrete parts (say 1sec)
For each sample part develop a fingerprint that approximates the sample (say taking 5-7 high and low peaks, normalizing them, and then hashing them
You can now either keep each fingerprint individually (in a collection), or run a transform over the sequence to generate a single fingerprint depending on your needs. Mostly you would just append the sequences together to get a linear fingerprint in 1 sec intervals.
To compare the fingerprint, you run the same process over the second sample, and then use a Diff algorithm to compare the two, using some "fuzz" to decide how close they are. You will need to compare the fingerprints on two dimensions, the order of the discrete fingerprints, as well as the overall difference in each sample.
This article on making a rough Java equivalent to Shazaam was posted a while ago: http://www.redcode.nl/blog/2010/06/creating-shazam-in-java/ and may be of some help to you.
Does anybody know of a way I can calculate very large integers in c#
I am trying to calculate the factorial of numbers e.g.
5! = 5*4*3*2*1 = 120
with small numbers this is not a problem but trying to calculate the factorial of the bigest value of a unsigned int which is 4,294,967,295 it doesn't seem possible.
I have looked into the BigInteger class but it doesn't seem to do what I need
any help would be greatly appreciated
To calculate the factorial of uint.MaxValue you'd need a lot of storage.
For example, the Wikipedia article as 8.2639316883... × 10^5,565,708. You're going to gain information like crazy.
I strongly suspect you're not going find any way of calculating it on a sane computer in a sane amount of time. Why do you need this value? Would Stirling's approximation be close enough?
Firstly, it's worth pointing out that the factorial of uint.MaxValue is astronomically large. I'm not able to find a good estimate of the order of magnitude of its factorial, but its bit representation will probably occupy a high percentage of a standard RAM, if not well exceed.
A BigInteger class seems to be what you want, providing you only want to go up to around 1,000,000 or so (very roughly). After that, time and memory become very prohibitive. In current (stable) versions of .NET, up to 3.5, you have to go with a custom implementation. This one on the CodeProject seems to be highly rated. If you happen to be developing for .NET 4.0, the Microsoft team have finally gotten around to including a BigInteger class in the System.Numerics namespace of the BCL. Unlike some BigInteger implementations, the one existing in .NET 4.0 doesn't have a built-in factorial method (I'm not sure about the CodeProject one), but it should be trivial to implement one - an extension method would be a nice way.
Since you seem to think you don't want to use a BigInteger type, it would be helpful if you could verify that it's not what you want having read my reply, and then explain precisely why it doesn't suit your purposes.
4294967295! = 10^(10^10.597) ~ 10^(40000000000)
This value requires about 40 Gb of RAM to store, even if you will find any BigInteger implementation for C#!
P.S. Well, with optimized storing, let's say 9 digits in 4 bytes, it will take ~18 Gb of RAM.
Why do you think that you need to calculate those factorials? It's not practiacally useful for anything to do the actual calculations.
Just the result of calculating factorial of (2^32-1) would take up a lot of space, approximately 16 GB.
The calculation itself will of course take a lot of time. If you build the program so that you can transfer the calculation process to faster hardware as it is invented, you should be able to get the result within your lifetime.
If it's something like an Euler problem that you are trying to solve, consider that a lot of solutions are found by elliminating what it is that you actually don't have to calculate in order to get the answer.
Here .
The fastest one, straight from the Factorial Man - Peter Luschny.
You can use the BigInteger class from the J# libraries for now. Here's an article on how. It makes deployment harder because you have to send out the J# redistributable. You can also consider going to VS2010 beta as Framework 4.0 will have BigInteger.
In case you have J# redist installed, an alternative way would be using java.math.BigInteger by adding a reference to the vjslib assembly.
Try to use an array for this task. You could use as long integers as you have free memory space. Every member of array repsesents one decimal digit. The only you need is to implement multipication.
If you are doing calculations with factorials like combinations for example you rarely need to multiply all the way down to 1 (eg. 98 * 98 * 97 since everything else cancels out).
Currently I am borrowing java.math.BigInteger from the J# libraries as described here. Having never used a library for working with large integers before, this seems slow, on the order of 10 times slower, even for ulong length numbers. Does anyone have any better (preferably free) libraries, or is this level of performance normal?
As of .NET 4.0 you can use the System.Numerics.BigInteger class. See documentation here: http://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx
Another alternative is the IntX class.
IntX is an arbitrary precision
integers library written in pure C#
2.0 with fast - O(N * log N) - multiplication/division algorithms
implementation. It provides all the
basic operations on integers like
addition, multiplication, comparing,
bitwise shifting etc.
F# also ships with one. You can get it at Microsoft.FSharp.Math.
The System.Numerics.BigInteger class in .NET 4.0 is based on Microsoft.SolverFoundation.Common.BigInteger from Microsoft Research.
The Solver Foundation's BigInteger class looks very performant. I am not sure about which license it is released under, but you can get it here (download and install Solver Foundation and find the Microsoft.Solver.Foundation.dll).
I reckon you could optimize the implementation if you perform all the operations on BigInts that are going to return results smaller than a native type (Eg. int64) on the native types and only deal with the big array if you are going to overflow.
edit
This implementation on codeproject, seems only 7 times slower ... But with the above optimization you could get it to perform almost identically to native types for small numbers.
Here are several implementations of BigInteger in C#.
I've used Mono's BigInteger implementation, works pretty fast (I've used it in CompactFramework)
Bouncy Castle
Mono
I'm not sure about the performance, but IronPython also has a BigInteger class. It is in the Microsoft.Scripting.Math namespace.
Yes, it will be slow, and 10x difference is about what I'd expect. BigInt uses an array to represent an arbitrary length, and all the operations have to be done manually (as opposed to most math which can be done directly with the CPU)
I don't even know if hand-coding it in assembly will give you much of a performance gain over 10x, that's pretty damn close. I'd look for other ways to optimize it--sometimes depending on your math problem there are little tricks you can do to make it quicker.
I used Biginteger at a previous job. I don't know what kind of performance needs you have. I did not use it in a performance-intensive situation, but never had any problems with it.
This may sound like a strange suggestion, but have you tested the decimal type to see how fast it works?
The decimal range is ±1.0 × 10^−28 to ±7.9 × 10^28, so it may still not be large enough, but it is larger than a ulong.
There was supposed to be a BigInteger class in .NET 3.5, but it got cut.
This won't help you, but there was supposed to be a BigInteger class in .Net 3.5; it got cut, but from statements made at PDC, it will be in .Net 4.0. They apparently have spent a lot of time optimizing it, so the performance should be much better than what you're getting now.
Further, this question is essentially a duplicate of How can I represent a very large integer in .NET?
See the answers in this thread. You will need to use one of the third-party big integer libraries/classes available or wait for C# 4.0 which will include a native BigInteger datatype.
This Looks very promising. It is a C# Wrapper over GMP.
http://web.rememberingemil.org/Projects/GnuMpDotNet/GnuMpDotNet.html
There are also other BigInteger options for .Net here in particular, Mpir.Net
You can also use the Math.Gmp.Native Nuget package that I wrote. Its source code is available on GitHub, and documentation is available here. It exposes to .NET all of the functionality of the GMP library which is known as a highly-optimized arbitrary-precision arithmetic library.
Arbitrary-precision integer are represented by the mpz_t type. Operations on these integers all begin with the mpz_ prefix. For examples, mpz_add or mpz_cmp. Source code examples are given for each operation.