Problem with arithmetic using logarithms to avoid numerical underflow (take 2) - logarithm

I have two lists of fractions;
say A = [ 1/212, 5/212, 3/212, ... ]
and B = [ 4/143, 7/143, 2/143, ... ].
If we define A' = a[0] * a[1] * a[2] * ... and B' = b[0] * b[1] * b[2] * ...
I want to calculate a normalised value of A' and B'
ie specifically the values of A' / (A'+B') and B' / (A'+B')
My trouble is A are B are both quite long and each value is small so calculating the product causes numerical underflow very quickly...
I understand turning the product into a sum through logarithms can help me determine which of A' or B' is greater
ie max( log(a[0])+log(a[1])+..., log(b[0])+log(b[1])+... )
and that using logs I can calculate the value of A' / B' but how do I do A' / A'+B'
My best bet to date is to keep the number representations as fractions, ie A = [ [1,212], [5,212], [3,212], ... ] and implement my own arithmetic but it's getting clumsy and I have a feeling there is a (simple) way of logarithms I'm just missing....
The numerators for A and B don't come from a sequence. They might as well be random for the purpose of this question. If it helps the denominators for all values in A are the same, as are all the denominators for B.
Any ideas most welcome!
( ps. I asked a similar question 24 hours ago regarding the ratio A'/B' but it was actually the wrong question to ask. I'm actually after A'/(A'+B'). Sorry, my mistake. )

I see few ways here
First of all you can notice that
A' / (A'+B') = 1 / (1 + B'/A')
and you know how to calculate B'/A' with logarithms.
Another way is to implement your own rational arithmetic but you don't need to go far about it. Since you know that denominators are the same for the whole array, it immediately gives you
numerator(A') = numerator(a[0]) * numerator(a[1]) ...
denumerator(A') = denumerator(a[0]) ^ A.length
All you now need to do is to sum A' and B' which is easy and then multiply A' and 1/(A'+B') which is also easy. The hardest part here is to normalize resulting value which is done with modulo operation and is trivial.
Alternatively, since you most likely using some popular scripting language, most of them have classes for rational arithmetic built in, Python and Ruby have them for sure.

My best bet to date is to keep the number representations as fractions and implement my own arithmetic but it's getting clumsy
What language are you using? If you can overload operators, it should be really easy to make up a Fraction class that you can treat as a number pretty much everywhere.
As an example, determining whether a fraction A / B is larger than C / D is basically comparing whether A * D is larger than B * C.

Both A and B have the same denominator in each fraction you mention. Is that true for every term in the list? If that's so, why don't you factor that out when you calculate the product? The denominator will simply be X^n, when X is the value and n is the number of terms in the list.
If you do that, you'll have the opposite problem: overflow in the numerator. You know that it can't be smaller than max(X)^n, where max(X) is the maximum value in the numerator and n is the number of terms in the list. If you can calculate that, you can see if your computer will have a problem. You can't put 10 pounds of anything in a 5 pound bag.
Unfortunately, the properties of logarithms limit you to the following simplifications:
(source: equationsheet.com)
and
(source: equationsheet.com)
So you're stuck with:
(source: equationsheet.com)
If you're using a language that supports infinite precision numbers (e.g., Java BigDecimal) it might make your life a little easier. But there's still a good argument for doing some thinking before you compute. Why use brute force when you can be elegant?

Well ... if you know A'(A'+B'), then B'(A'+B') should be one minus that. I personally would not use logarithms. I would use the actual fractions. I would also use some sort of BigInt class to represent the numerator and denominator. Which language are you using? Python can be a good fit.

Related

RSA Prime Generation using Provable vs Probable Prime Construction

I am trying to implement RSA prime generation for P and Q based on FIP186-4 specification. The specification describes two different implementations: Section 3.2 Provable Prime Construction vs. Section 3.3 Probable Prime Construction. Initially, I tried implementing the probable prime approach because it is easier to understand and implement, but I discovered it is very slow because of the number of iterations needed to find P and Q primes (worst case it takes 15 minutes). Next, I decided to try the provable prime approach but I found out the algorithm is much more complex and might be slow as well. Below are my two issues:
In Section C.10, Step 12, how to eliminate the sqrt(2) to the expression x = floor(sqrt(2))(2^(L−1))) + (x mod (2^L − floor((sqrt(2)(2^(L−1))))) so that I can represent it as whole numbers using BigNum representation?
In Section C.10, Step 14, is there a fast way to compute y in the interval [1, p2] such that 0 = ( y p0 p1–1) mod p2? The specification doesn't specify a method to implement this. My initial thought was to perform a linear search staring from integer 1 and up but that can be very slow because p2 can be a very large number.
I tried searching online for help on this issue, but I discovered a lot of examples don't even comply with FIPS186-4. I assume it is because these two methods are too slow.

Double sqrt solution in Matlab?

I would like to know how can I get both the positive and the negative solution from a sqrt in Matlab.
For example if I have:
sin(a) = sqrt(1-cos(a)^2);
The docs don't say anything specific about always only providing the positive square root but it does seem like a fair assumption in which case you can get the negative square pretty easily like this:
p = sqrt(1-cos(a)^2);
n = -sqrt(1-cos(a)^2);
btw assigning to sin(a) like that is going to create a variable called sin which will hide the sin function leading to many possible errors, so I would highly recommend choosing a different variable name.
MATLAB (and every other programming language that I know of) only returns the principal square root of x when calling sqrt(x) or equivalent.
How you'd write the square root of x mathematically, is
s = ±√x
which is just a shorthand for writing the whole solution set
s = {+√x -√x}
In MATLAB, you'd write it the same as this last case, but with slightly different syntax,
s = [+sqrt(x) -sqrt(x)]
which can be computed more efficiently if you "factor out" the sqrt:
s = sqrt(x) * [1 -1]
So, for your case,
s = sqrt(1-cos(a)^2) * [1 -1]
or, if you so desire,
s = sin(acos(a)) * [1 -1]
which is a tad slower, but perhaps more readable (and actually a bit more accurate as well).
Now of course, if you can somehow find the components whose quotient results in the value of your cosine, then you wouldn't have to deal with all this messy business of course....
sqrt does not solve equations, only gives numerical output. You will need to formulate your equation as you need it, and then you can use sqrt(...) -1*sqrt(...) to give your positive and negative outputs.

Dot Product: * Command vs. Loop gives different results

I have two vectors in Matlab, z and beta. Vector z is a 1x17:
1 0.430742139435890 0.257372971229541 0.0965909090909091 0.694329541928697 0 0.394960106863064 0 0.100000000000000 1 0.264704325268675 0.387774594078319 0.269207605609567 0.472226643323253 0.750000000000000 0.513121013402805 0.697062571025173
... and beta is a 17x1:
6.55269487769363e+26
0
0
-56.3867588816768
-2.21310778926413
0
57.0726052009847
0
3.47223691057151e+27
-1.00249317882651e+27
3.38202232046686
1.16425987969027
0.229504956512063
-0.314243264212449
-0.257394312588330
0.498644243389556
-0.852510642195370
I'm dealing with some singularity issues, and I noticed that if I want to compute the dot product of z*beta, I potentially get 2 different solutions. If I use the * command, z*beta = 18.5045. If I write a loop to compute the dot product (below), I get a solution of 0.7287.
summation=0;
for i=1:17
addition=z(1,i)*beta(i);
summation=summation+addition;
end
Any idea what's going on here?
Here's a link to the data: https://dl.dropboxusercontent.com/u/16594701/data.zip
The problem here is that addition of floating point numbers is not associative. When summing a sequence of numbers of comparable magnitude, this is not usually a problem. However, in your sequence, most numbers are around 1 or 10, while several entries have magnitude 10^26 or 10^27. Numerical problems are almost unavoidable in this situation.
The wikipedia page http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems shows a worked example where (a + b) + c is not equal to a + (b + c), i.e. demonstrating that the order in which you add up floating point numbers does matter.
I would guess that this is a homework assignment designed to illustrate these exact issues. If not, I'd ask what the data represents to suss out the appropriate approach. It would probably be much more productive to find out why such large numbers are being produced in the first place than trying to make sense of the dot product that includes them.

Accurate matrix multiplication in Matlab

There are 2 matrices:
A: (6 x 78) max=22.2953324329113, min=0
B: (6 x 6 ) max=2187.9013214004 , min=-377.886378385521
B is symmetric and as a result, C = A' * B * A must be a symmetric matrix (theoretically), but this is not the case when I calculate them in Matlab. In fact:
max(max(abs(C - C'))) = 2.3283064365386963e-010
How can I multiply them and get an accurate result?
or
What is a safe way to round the elements of C?
I read this question : efficient-multiplication-of-very-large-matrices-in-matlab, but my problem is not speed or memory. I need an accurate result
Thanks.
You can consider cholesky decomposition of B since it is symmetric
B = R'R
R = chol(A) % // in matlab
then C = A'R'R A =D'D, where D = RA.
With C=D'D you should have machine epsilon precision, although you introduce a possible error due to the accuracy of the decomposition.
You need to read "What Every Computer Scientist Should Know About Floating-Point Arithmetic":
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Realize that computers will never be able to give perfect floating point results, and that leaves you with a few options:
Do as few operations as possible, that is, pick the order of operations for the purpose of having the fewest rounding errors
Fixed decimal point arithmetic - or integer arithmetic - this isn't always practical for all applications, but in some applications, you can get away with this. Financial applications are the commonly cited example (multiply by 100 to make pennies go away! divide by 100 when you are done!).
There are other tricks I can't think of this late.
I'm going to have to give your operations a spin - on my machine, eps gives me 2.2204e-16, which is six orders of magnitude lower than what you are getting. See what eps is on your machine - it should be similar - if it is something like 1e-12 or so, I'd say your result is exactly what you'd expect from those operations.
When I do this with random numbers, I get
a = rand(6, 78);
b = rand(6, 6);
b = b + b'; % To make b symmetric
c = a' * b * a;
max(max(abs(c - c')))
ans =
7.1054e-15
Which is a bit closer to what I'd expect with rounding errors after that many operations, but I am not sure of your input, your machine, and I have no idea what else might be affecting things.
Cheers,--

How can I elegantly determine a central interval of a given distance M in an array of length N?

I have an array x=1:N. I want to visualize the central part of a curve determined by x, say only the part xx=N/2-M/2:N/2+M/2. I know I can do this if I round everything (N and M can be anything), but this makes a simple indexing operation quite lengthy and unreadable. Is there a more elegant way of doing this?
Adjust your thinking, express the size of the interval in terms of its 'radius' (call it m) rather than its 'diameter' (M) and, voila
xx = median(x)-m:median(x)+m
That's way more elegant, isn't it ! Since you'll probably want integers everywhere try
xx = floor(median(x)-m):ceil(median(x)+m)
Rounding is implicitly done by MATLAB on integer types, so you can simply convert M and N to integers:
N = uint32(N);
M = uint32(M);
xx = N/2-M/2:N/2+M/2;