Inverse-square law equation - c

I have a light sensor which reads light intensity from 0 to 4095. I struggling to to write an equation using the inverse-square law of light so that when the light is lowest (let's say lowest ambient light is 50), it returns 1, and if highest (4095), it returns 26, but crucially the increments from 1 to 26 require the light to increase exponentially i.e.:
123 4 5 6 7 8 9 10 ...27
light intensity ->
Any suggestions of an equation? I can't seem to figure it out. Language is C.

You are wanting to divide your 4095 to 50 interval into 25 equal segments (26-1). That would mean the width of each "intensity segment" is:
(4095-50)/25 = 161.8
So if variable x is ranging 1 to 26, your equation for distance would be:
D = sqrt( 1 / (4095 - (x * 161.8)) )
This is from taking Intensity_value = 1/D^2 as the proportion (I say "intensity value" since this doesn't include the proportion constant if it were a real intensity - we're dealing with arbitrary units for this problem).
In other words, if you plotted x on a line and each x value was a distance D from the origin, you'd get the result you are showing for 1 through 26. I am assuming, from your diagram, that the intensity is DECREASING as you go to the right.
You should be able to generalize this for different ranges of intensities and different ranges of corresponding x.

Try the inverse of I = a.R^2 + b with a = 4090/676 and b = -1, where I is the intensity.
I have obtained this by assuming the above function and inserting the value pairs 1,50 and 26,4095 and solving for a and b.

If your intent is to find some exponential function on domain [1,4095] with values in range [1,26] then this will satisfy these conditions:
f(x) = exp [ ( x - 50) * ln( 26) / ( 4095 - 50)]
If your intent is to find function that satisfies inverse square law then since;
this will work:
(f( x))^2 = ( 1 / ( 4095 - ( x * ( 4095 - 50) / 25)) )
f(x) = sqrt( 1 / ( 4095 - ( x * ( 4095 - 50) / 25)) )

I have no idea of physics, but from your explanation I believe you are looking for logarithmic interpolation; this could be done as follows.
y = ln(x-50) * (26 - 1 / ln(4095-50) ) + 1
Here 50, 26 and 1 are used as parameters to stretch and shift the function to map 50 to 1 and 4095 to 26; I hope this helps.

Related

binomial coefficient for very high numbers in c

So the task I have to solve is to calculate the binomial coefficient for 100>=n>k>=1 and then say how many solutions for n and k are over an under barrier of 123456789.
I have no problem in my formula of calculating the binomial coefficient but for high numbers n & k -> 100 the datatypes of c get to small to calculated this.
Do you have any suggestions how I can bypass this problem with overflowing the datatypes.
I thought about dividing by the under barrier straight away so the numbers don't get too big in the first place and I have to just check if the result is >=1 but i couldn't make it work.
Say your task is to determine how many binomial coefficients C(n, k) for 1 ≤ k < n ≤ 8 exceed a limit of m = 18. You can do this by using the recurrence C(n, k) = C(n − 1, k) + C(n − 1, k − 1) that can visualized in Pascal's triangle.
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 (20) 15 6 1
1 7 (21 35 35 21) 7 1
1 8 (28 56 70 56 28) 8 1
Start at the top and work your way down. Up to n = 5, everything is below the limit of 18. On the next line, the 20 exceeds the limit. From now on, more and more coefficients are beyond 18.
The triangle is symmetric and strictly increasing in the first half of each row. You only need to find the first element that exceeds the limit on each line in order to know how many items to count.
You don't have to store the whole triangle. It is enough to keey the last and current line. Alternatively, you can use the algorithm detailed [in this article][ot] to work your way from left to right on each row. Since you just want to count the coefficients that exceed a limit and don't care about their values, the regular integer types should be sufficient.
First, you'll need a type that can handle the result. The larget number you need to handle is C(100,50) = 100,891,344,545,564,193,334,812,497,256. This number requires 97 bits of precision, so your normal data types won't do the trick. A quad precision IEEE float would do the trick if your environment provides it. Otherwise, you'll need some form of high/arbitrary precision library.
Then, to keep the numbers within this size, you'll want cancel common terms in the numerator and the denominator. And you'll want to calculate the result using ( a / c ) * ( b / d ) * ... instead of ( a * b * ... ) / ( c * d * ... ).

Check subset sum for special array equation

I was trying to solve the following problem.
We are given N and A[0]
N <= 5000
A[0] <= 10^6 and even
if i is odd then
A[i] >= 3 * A[i-1]
if i is even
A[i]= 2 * A[i-1] + 3 * A[i-2]
element at odd index must be odd and at even it must be even.
We need to minimize the sum of the array.
and We are given a Q numbers
Q <= 1000
X<= 10^18
We need to determine is it possible to get subset-sum = X from our array.
What I have tried,
Creating a minimum sum array is easy. Just follow the equations and constraints.
The approach that I know for subset-sum is dynamic programming which has time complexity sum*sizeof(Array) but since sum can be as large as 10^18 that approach won't work.
Is there any equation relation that I am missing?
We can make it with a bit of math:
sorry for latex I am not sure it is possible on stack?
let X_n be the sequence (same as being defined by your A)
I assume X_0 is positive.
Thus sequence is strictly increasing and minimization occurs when X_{2n+1} = 3X_{2n}
We can compute the general term of X_{2n} and X_{2n+1}
v_0 =
X0
X1
v_1 =
X1
X2
the relation between v_0 and v_1 is
M_a =
0 1
3 2
the relation between v_1 and v_2 is
M_b =
0 1
0 3
hence the relation between v_2 and v_0 is
M = M_bM_a =
3 2
9 6
we deduce
v_{2n} =
X_{2n}
X_{2n+1}
v_{2n} = M^n v_0
Follow the classical diagonalization... and we (unless mistaken) get
X_{2n} = 9^n/3 X_0 + 2*9^{n-1}X_1
X_{2n+1} = 9^n X_0 + 2*9^{n-1}/3X_1
recall that X_1 = 3X_0 thus
X_{2n} = 9^n X_0
X_{2n+1} = 3.9^n X_0
Now if we represent the sum we want to check in base 9 we get
9^{n+1} 9^n
___ ________ ___ ___
X^{2n+2} X^2n
In the X^{2n} places we can only put a 1 or a 0 (that means we take the 2n-th elem from the A)
we may also put a 3 in the place of the X^{2n} place which means we selected the 2n+1th elem from the array
so we just have to decompose number in base 9, and check whether all its digits or either 0,1 or 3 (and also if its leading digit is not out of bound of our array....)

MATLAB function to replace randi to generate a matrix

I have a matlab problem to solve. In have two vectores that limit my space, x_low and x_high. The matrix pos needs to have values within this spaces and each column of the matrix has different bounds given by the two vectores. Now my problem is that randi gives valus between two integers but i need to change the bounds for each columns. There is another way to use randi or a different matlab function to do this?
I know there are better codes to do this but i'm starting to use matlab and i know to do it this way, any aid is welcome
x_low = [Io_low, Iirr_low, Rp_low, Rs_low, n_low]; % vector of constant values
x_high = [Io_high, Iirr_high, Rp_high, Rs_high, n_high]; % vector of constant values
pos = rand(particles, var);
var = length(x_high);
for i = 1: particles % rows
for k = 1: var %columns
if pos(i, k) < x_low(k) || pos(i, k) > x_high(k) % if the position is out of bounder
pos(i, k) = randi(x_low(k), x_high(k), 1); % fill it with a particle whithin the bounderies
end
end
end
If I understand correctly, you need to generate a matrix with integer values such that each column has different lower and upper limits; and those lower and upper limits are inclusive.
This can be done very simply with
rand (to generate random numbers between 0 and 1 ),
bsxfun (to take care of the lower and upper limits on a column basis), and
round (so that the results are integer values).
Let the input data be defined as
x_low = [1 6 11]; %// lower limits
x_high = [3 10 100]; %// upper limits
n_rows = 7; %// number of columns
Then:
r = rand(n_rows, numel(x_low)); %// random numbers between 0 and 1
r = floor(bsxfun(#times, r, x_high-x_low+1)); %// adjust span and round to integers
r = bsxfun(#plus, r, x_low); %// adjust lower limit
gives something like
r =
2 7 83
3 6 93
2 6 22
3 10 85
3 7 96
1 10 90
2 8 57
If you need to fill in values only at specific entries of matrix pos, you can use something like
ind = bsxfun(#lt, pos, x_low) | bsxfun(#gt, pos, x_high); %// index of values to replace
pos(ind) = r(ind);
This a little overkill, because the whole matrixd r is generated only to use some of its entries. To generate only the needed values the best way is probably to use loops.
You can use cellfun for this. Something like:
x_low = [Io_low, Iirr_low, Rp_low, Rs_low, n_low];
x_high = [Io_high, Iirr_high, Rp_high, Rs_high, n_high];
pos = cell2mat(cellfun(#randi, mat2cell([x_low' x_high'], ones(numel(x_low),1), 1), repmat({[particles 1]}, [numel(x_low) 1)])))';
Best,

How to generate a multiplicative space vector in Matlab?

I am trying to generate "automatically" a vector 0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30 (in multiplicative space).
I know linspace and logspace functions, but I couldn't find any similar function for multiplicative space.
Is there any? Otherwise, how to generate a vector like the one I need?
An easy way with bsxfun, also considering multiplication to smaller spaces:
x = [0.01,0.03,0.05] % initial vector, works for various lengths
n = 12; % times it should get multiplied in rising direction
m = 3; % times it should get multiplied in falling direction
Z = bsxfun( #times, x(:), 10.^(-m:n) )
Z = Z(:)
% if preferred, bulky one-liner:
% Z = reshape( bsxfun( #times, x(:), 10.^(-m:n) ) , 1 , [])
I assumed a multiplication with the multiplication vector, e.g.:
10.^(0:n) = 1 10 100 1000 10000 100000 ....
But custom vectors Y are also possible:
Z = bsxfun( #times, x(:), Y(:)' ) Z = Z(:)
A function that might help you achieving this in a very easy and compact way is the Kronecker tensor product kron.
You can use it to rewrite thewaywewalk's answer as:
v = [0.01;0.03;0.05]; % initial vector
emin = -3; % minimal exponent
emax = 12; % maximal exponent
Z = kron(10.^(emin:emax)',v(:))
which should give you the exact same result.
not very efficient but this will generate what you want. inputvec is your initial vector [0.01 0.03] in this case, multiplier is 10. length of the required string n is 8. n should be a multiple of nn (length of the input vector)
function newvec=multispace(n,inputvec,multiplier)
nn=length(inputvec);
newvec=zeros(1,n);
newvec(1:nn)=inputvec;
for i=1:n/nn-1
newvec(i*nn+1:(i+1)*nn)=(newvec((i-1)*nn+1:(i)*nn)).*multiplier;
end
end

What does "linear interpolation" mean?

I often hear the term "linear interpolation" in context with animations in WPF. What exactly does "linear interpolation" mean? Could you give me an example where to use "linear interpolation"?
Linear means lines (straight ones).
Interpolation is the act of finding a point within two other points. Contrast this with extrapolation, which is finding a point beyond the ends of a line.
So linear interpolation is the use of a straight line to find a point between two others.
For example:
*(5,10)
/
/
/
/
*(0,0)
You can use the two endpoints with linear interpolation to get the points along the line:
(1,2)
(2,4)
(3,6)
(4,8)
and linear extrapolation to get (for example):
(1000,2000)
(-1e27,-2e27)
In animation, let's say you have a bouncing ball that travels from the (x,y) position of (60,22) to (198,12) in 10 seconds.
With an animation rate of 10 frames per second, you can calculate it's position at any time with:
x0 = 60, y0 = 22
x1 = 198, y1 = 12
frames = 100
for t = 0 to frames:
x = (x1 - x0) * (t / frames) + x0
y = (y1 - y0) * (t / frames) + y0
Those two formulae at the bottom are examples of linear interpolation. At 50% (where t == 50):
x = (198 - 60) * (50 / 100) + 60
= 138 * 0.5 + 60
= 69 + 60
= 129
y = (12 - 22) * (50 / 100) + 22
= -10 * 0.5 + 22
= -5 + 22
= 17
and (129,17) is the midpoint between the starting and ending positions.
E.g. when you want a storyboard to move an element from one position to another using a fixed speed, then you'd use linear interpolation between the start and end positions.

Resources