I wanna fill my array in Julia by positive real numbers. But I found information only how to do it with integers or real numbers (including negatives). Is it possible?
Thanks!
You can use any mathematical formula that maps the [0, 1) range into the [0, +inf]:
For example, if x is your random variable in the [0, 1) range (obtained with e.g. rand() for float data types):
tan(x * pi / 2)
atanh(x)
log(x) ^ 2
-log(x) / x ^ p (for p non-negative integer -- it will change the number distribution)
There are many other functions.
Of course the numbers are no longer uniformly distributed, but that is impossible to achieve.
Technically, the built-in randexp fulfils your requirement: the exponential distribution has the positive reals as its support. The scale of the numbers you practically get is much lower, though. The same holds for abs ∘ randn, the half-normal distribution. (In both cases, you could multiply the results with a large positive number to increase the variance to your requirements.)
Here's a funny alternative: you can generate uniformly random bits, and reinterpret them as floats (and just set the sign always to positive):
julia> bitrand(3*64).chunks
3-element Vector{UInt64}:
0xe7c7c52703987e68
0xc221b9864e7bab7e
0xa45b39faa65b446e
julia> reinterpret(Float64, bitrand(3*64).chunks)
3-element reinterpret(Float64, ::Vector{UInt64}):
2.8135484124856866e-108
-4.521596431965459e53
-5.836451011310255e78
julia> abs.(reinterpret(Float64, bitrand(3*64).chunks))
3-element Vector{Float64}:
1.6467305137006711e236
3.3503597018864875e-260
1.2211675821672628e77
julia> bitstring.(abs.(reinterpret(Float64, bitrand(3*64).chunks)))
3-element Vector{String}:
"0000110000011000001110000110001111010000011110111101000101101101"
"0011000010110101111100111011110100111100011011000101001100010011"
"0110111000001000101011010100011011010010100111111011001000001100"
This is still not a uniform distribution on the values, though, as the precision of floats gets smaller the larger the exponent gets.
Related
I have a power series with all terms non-negative which I want to evaluate to some arbitrarily set precision p (the length in binary digits of a MPFR floating-point mantissa). The result should be faithfully rounded. The issue is that I don't know when should I stop adding terms to the result variable, that is, how do I know when do I already have p + 32 accurate summed bits of the series? 32 is just an arbitrarily chosen small natural number meant to facilitate more accurate rounding to p binary digits.
This is my original series
0 <= h <= 1
series_orig(h) := sum(n = 0, +inf, a(n) * h^n)
But I actually need to calculate an arbitrary derivative of the above series (m is the order of the derivative):
series(h, m) := sum(n = m, +inf, a(n) * (n - m + 1) * ... * n * h^(n - m))
The rational number sequence a is defined like so:
a(n) := binomial(1/2, n)^2
= (((2*n)!/(n!)) / (n! * 4^n * (2*n - 1)))^2
So how do I know when to stop summing up terms of series?
Is the following maybe a good strategy?
compute in p * 4 (which is assumed to be greater than p + 32).
at each point be able to recall the current partial sum and the previous one.
stop looping when the previous and current partial sums are equal if rounded to precision p + 32.
round to precision p and return.
Clarification
I'm doing this with MPFI, an interval arithmetic addon to MPFR. Thus the [mpfi] tag.
Attempts to get relevant formulas and equations
Guided by Eric in the comments, I have managed to derive a formula for the required working precision and an equation for the required number of terms of the series in the sum.
A problem, however, is that a nice formula for the required number of terms is not possible.
Someone more mathematically capable might instead be able to achieve a formula for a useful upper bound, but that seems quite difficult to do for all possible requested result precisions and for all possible values of m (the order of the derivative). Note that the formulas need to be easily computable so they're ready before I start computing the series.
Another problem is that it seems necessary to assume the worst case for h (h = 1) for there to be any chance of a nice formula, but this is wasteful if h is far from the worst case, that is if h is close to zero.
I have an 80 element array with the same entries: 176.01977965813853
If I use the mean function I will get the value 176.01977965813842
Why is that?
Here is a minimal working example:
using Statistics
arr = fill(176.01977965813853, 80)
julia> mean(arr)
176.01977965813842
I expected this to return 176.01977965813853.
These are just expected floating point errors. But if you need very precise summations, you can use a a bit more elaborate (and costly) summation scheme:
julia> using KahanSummation
[ Info: Precompiling KahanSummation [8e2b3108-d4c1-50be-a7a2-16352aec75c3]
julia> sum_kbn(fill(176.01977965813853, 80))/80
176.01977965813853
Ref: Wikipedia
The problem as I understand it can be reproduced as follows:
using Statistics
arr = fill(176.01977965813853, 80)
julia> mean(arr)
176.01977965813842
The reason for this is that julia does all floating point arithmetic with 64 bits of precision by default (i.e. the Float64 type). Float64s cannot represent any real number. There is a finite step between each floating point number and rounding errors are incurred when you do arithmetic on them. These rounding errors are usually fine, but if you're not careful, they can be catastrophic. For instance:
julia> 1e100 + 1.0 - 1e100
0.0
That says that if I do 10^100 + 1 - 10^100 I get zero! If you want to get an upper bound on the errors caused by floating point arithmetic, we can use IntervalArithmetic.jl:
using IntervalArithmetic
julia> 1e100 + interval(1.0) - 1e100
[0, 1.94267e+84]
That says that the operation 1e100 + 1.0 - 1e100 is at least equal to 0.0 and at most 1.94*10^84, so the error bounds are huge!
We can do the same for the operation you were interested in,
arr = fill(interval(176.01977965813853), 80);
julia> mean(arr)
[176.019, 176.02]
julia> mean(arr).lo
176.019779658138
julia> mean(arr).hi
176.0197796581391
which says that the actual mean could be at least 176.019779658138 or at most 176.0197796581391, but one can't be any more certain due to floating point error! So here, Float64 gave the answer with at most 10^-13 percent error, which is actually quite small.
What if those are unacceptable error bounds? Use more precision! You can use the big string macro to get arbitrary precision number literals:
arr = fill(interval(big"176.01977965813853"), 80);
julia> mean(arr).lo
176.0197796581385299999999999999999999999999999999999999999999999999999999999546
julia> mean(arr).hi
176.019779658138530000000000000000000000000000000000000000000000000000000000043
That calculation was done using 256 bits of precision, but you can get even more precision using the setprecision function:
setprecision(1000)
arr = fill(interval(big"176.01977965813853"), 80);
julia> mean(arr).lo
176.019779658138529999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999599
julia> mean(arr).hi
176.019779658138530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000579
Note that arbitrary precision arithmetic is sloooow compared to Float64s, so it's usually best to just use arbitrary precision arithmetic to validate your results to make sure you're converging to a good result within your desired accuracy.
I'm looking at the numerics of some matrices that depends on a parameter x. The matrix has real eigenvalues for certain values x, but for other values I have a degeneracy in both eigenvalues and eigenvectors (the occurrence of exceptional points).
One of the simplest examples to get an exceptional point is with the matrix:
julia> h=[1 1im; 1im -1]
2×2 Array{Complex{Int64},2}:
1+0im 0+1im
0+1im -1+0im
The eigenvalues are zero, as they should be
2-element Array{Complex{Float64},1}:
-2.22045e-16+0.0im
0.0+0.0im
However, I would like to know why Julia give me the eigenvectors:
julia> b[2][:,1]
2-element Array{Complex{Float64},1}:
-0.0-0.707107im
0.707107+0.0im
julia> b[2][:,2]
2-element Array{Complex{Float64},1}:
0.707107+0.0im
0.0+0.707107im
Since in this case the eigenvalue is zero, I think it doesn't really matter what is the associated eigenvector. But if the eigenvalues coalesce somewhere in the
complex plane, do I really get two equal eigenvectors?
Is there an specific way to treat this cases in Julia?
The kernel of your matrix consists of multiples of (1,i)', which is what you get. As the matrix is not the zero matrix, it has rank 1 and thus also co-rank 1, the eigenspace has dimension 1. The generalized eigenspace is the full space, you get A*(1,0)' = (1,i)' so that in that basis ((1,i)',(1,0)') the linear operator has the matrix [[0,1],[0,0]], its Jordan normal form.
Recently i solved a problem where i have to compute (a-b)%n.The results were self explanatory when a-b is an positive number but for negative numbers the results that i got seems confusing..i just wanted to know how can we calculate this result for negative numbers.
Any links dealing with modulo operator properties are most welcome.
http://en.m.wikipedia.org/wiki/Modulo_operation
In many programming languages (C, Java) the modulo operator is defined so that the modulus has the same sign as the first operand. This means that the following equation holds:
(-a) % n = -(a % n)
For example, -8%3 would be -2, since 8%3 is 2.
Others, such as Python, compute a % n instead as the positive remainder when diving by n, which means
(-a) % n = n - (a % n)
For example, -8%3 is 1 because 3-(8%3) is 3-2 is 1.
Note that in modular arithmetic adding or subtracting any multiple of n does not change the result because "equality" (or congruence if you prefer that term) is defined with respect to divisibility: X is equal to 0 if it is a multiple of n, and A is equal to B if A-B is a multiple of n. For example -2 is equal to 1 modulo 3 because -2-1 = -3 is divisible by 3.
I have polynomials of nontrivial degree (4+) and need to robustly and efficiently determine whether or not they have a root in the interval [0,T]. The precise location or number of roots don't concern me, I just need to know if there is at least one.
Right now I'm using interval arithmetic as a quick check to see if I can prove that no roots can exist. If I can't, I'm using Jenkins-Traub to solve for all of the polynomial roots. This is obviously inefficient since it's checking for all real roots and finding their exact positions, information I don't end up needing.
Is there a standard algorithm I should be using? If not, are there any other efficient checks I could do before doing a full Jenkins-Traub solve for all roots?
For example, one optimization I could do is to check if my polynomial f(t) has the same sign at 0 and T. If not, there is obviously a root in the interval. If so, I can solve for the roots of f'(t) and evaluate f at all roots of f' in the interval [0,T]. f(t) has no root in that interval if and only if all of these evaluations have the same sign as f(0) and f(T). This reduces the degree of the polynomial I have to root-find by one. Not a huge optimization, but perhaps better than nothing.
Sturm's theorem lets you calculate the number of real roots in the range (a, b). Given the number of roots, you know if there is at least one. From the bottom half of page 4 of this paper:
Let f(x) be a real polynomial. Denote it by f0(x) and its derivative f′(x) by f1(x). Proceed as in Euclid's algorithm to find
f0(x) = q1(x) · f1(x) − f2(x),
f1(x) = q2(x) · f2(x) − f3(x),
.
.
.
fk−2(x) = qk−1(x) · fk−1(x) − fk,
where fk is a constant, and for 1 ≤ i ≤ k, fi(x) is of degree lower than that of fi−1(x). The signs of the remainders are negated from those in the Euclid algorithm.
Note that the last non-vanishing remainder fk (or fk−1 when fk = 0) is a greatest common
divisor of f(x) and f′(x). The sequence f0, f1,. . ., fk (or fk−1 when fk = 0) is called a Sturm sequence for the polynomial f.
Theorem 1 (Sturm's Theorem) The number of distinct real zeros of a polynomial f(x) with
real coefficients in (a, b) is equal to the excess of the number of changes of sign in the sequence f0(a), ..., fk−1(a), fk over the number of changes of sign in the sequence f0(b), ..., fk−1(b), fk.
You could certainly do binary search on your interval arithmetic. Start with [0,T] and substitute it into your polynomial. If the result interval does not contain 0, you're done. If it does, divide the interval in 2 and recurse on each half. This scheme will find the approximate location of each root pretty quickly.
If you eventually get 4 separate intervals with a root, you know you are done. Otherwise, I think you need to get to intervals [x,y] where f'([x,y]) does not contain zero, meaning that the function is monotonically increasing or decreasing and hence contains at most one zero. Double roots might present a problem, I'd have to think more about that.
Edit: if you suspect a multiple root, find roots of f' using the same procedure.
Use Descartes rule of signs to glean some information. Just count the number of sign changes in the coefficients. This gives you an upper bound on the number of positive real roots. Consider the polynomial P.
P = 131.1 - 73.1*x + 52.425*x^2 - 62.875*x^3 - 69.225*x^4 + 11.225*x^5 + 9.45*x^6 + x^7
In fact, I've constructed P to have a simple list of roots. They are...
{-6, -4.75, -2, 1, 2.3, -i, +i}
Can we determine if there is a root in the interval [0,3]? Note that there is no sign change in the value of P at the endpoints.
P(0) = 131.1
P(3) = 4882.5
How many sign changes are there in the coefficients of P? There are 4 sign changes, so there may be as many as 4 positive roots.
But, now substitute x+3 for x into P. Thus
Q(x) = P(x+3) = ...
4882.5 + 14494.75*x + 15363.9*x^2 + 8054.675*x^3 + 2319.9*x^4 + 370.325*x^5 + 30.45*x^6 + x^7
See that Q(x) has NO sign changes in the coefficients. All of the coefficients are positive values. Therefore there can be no roots larger than 3.
So there MAY be either 2 or 4 roots in the interval [0,3].
At least this tells you whether to bother looking at all. Of course, if the function has opposite signs on each end of the interval, we know there are an odd number of roots in that interval.
It's not that efficient, but is quite reliable. You can construct the polynomial's Companion Matrix (A sparse matrix whose eigenvalues are the polynomial's roots).
There are efficient eigenvalue algorithms that can find eigenvalues in a given interval. One of them is the inverse iteration (Can find eigenvalues closest to some input value. Just give the middle point of the interval as the above value).
If the value f(0)*f(t)<=0 then you are guaranteed to have a root. Otherwise you can start splitting the domain into two parts (bisection) and check the values in the ends until you are confident there is no root in that segment.
if f(0)*f(t)>0 you either have no, two, four, .. roots. Your limit is the polynomial order. if f(0)*f(t)<0 you may have one, three, five, .. roots.