Convert floating number to "prime" fraction - matlab

Sorry for a possibly misleading title.
Given a floating point input "A", we need factor it as
Q = A + B/C
where A is integer part of Q, so basically fix(Q), and B & C must be coprime to one other.
Example:
Q = 14.7419 => Q = 14 + 23/31
So that
A = 14, B = 23, C = 31
Is there a way to get B and C with intrinsic matlab functions? If not, I would appreciate a guidance in the right direction :)
Thanks in advance.

The solution here would not be the rats function as suggested by beaker under the question, but the rat function:
Q = 14.7419;
A = fix( Q )
[B,C] = rat( Q-A, 0.001)
The second argument to rat is the tolerance.
For further details please refer to https://www.mathworks.com/help/matlab/ref/rat.html.

Related

The Guillou-Quisquater Identification Scheme

Can you please elucidate how it is computed? I am desperate .... i don't know what i am missing here.
Example:
Suppose the TA chooses p = 467 and q = 479, so n = 223693. Suppose also that b = 503 and Alice’s secret integer u = 101576. Then she will compute
Original_formula
How can I compute (u^(-1))^b to be larger than n (or at least larger than 0)? What am I missing?
Original source: http://flylib.com/books/en/3.230.1.96/1/

Matlab: Finding two unknown constants/parameters in an equation

I've read up on fsolve and solve, and tried various methods of curve fitting/regression but I feel I need a bit of guidance here before I spend more time trying to make something work that might be the wrong approach.
I have a series of equations I am trying to fit to a data set (x) separately:
for example:
(a+b*c)*d = x
a*(1+b*c)*d = x
x = 1.9248
3.0137
4.0855
5.0097
5.7226
6.2064
6.4655
6.5108
6.3543
6.0065
c= 0.0200
0.2200
0.4200
0.6200
0.8200
1.0200
1.2200
1.4200
1.6200
1.8200
d = 1.2849
2.2245
3.6431
5.6553
8.3327
11.6542
15.4421
19.2852
22.4525
23.8003
I know c, d and x - they are observations. My unknowns are a and b, and should be constant.
I could do it manually for each x observation but there must be an automatic and far superior way or at least another approach.
Very grateful if I could receive some guidance. Thanks for the time!
Given your two example equations; let y=x./d, then
y = a+b*c
y = a+a*b*c
The first case is just a line, for which you can obtain a least squares fit (values for a and b) with polyfit(). In the second case, you can just say k=a*b (since these are both fitted anyway), then rewrite it as:
y = a+k*c
Which is exactly the same line as the first problem, except now b = k/a. In fact, b=b1/a is the solution to the second problem where b1 is the fit from the first problem. In short, to solve them both, you need one call to polyfit() and a couple of divisions.
Will that work for you?
I see two different equations to fit here. To spell out the code:
For (a+b*c)*d = x
p = polyfit(c, x./d, 1);
a = p(2);
b = p(1);
For a*(1+b*c)*d = x
p = polyfit(c, x./d, 1);
a = p(2);
b = p(1) / a;
No need for polyfit; this is just a linear least squares problem, which is best solved with MATLAB's slash operator:
>> ab = [ones(size(c)) c] \ (x./d)
ans =
1.411437211703194e+000 % 'a'
-7.329687661579296e-001 % 'b'
Faster, cleaner, more educative :)
And, as Emmet already said, your second equation is nothing more than a different form of your first equation, the difference being that the b in your first equation, is equal to a*b in your second one.

Matlab using interp1 to find the index?

I have an array of Fa which contains values I found from a function. Is there a way to use interp1 function in Matlab to find the index at which a specific value occurs? I have found tutorials for interp1 which I can find a specific value in the array using interp1 by knowing the corresponding index value.
Example from http://www.mathworks.com/help/matlab/ref/interp1.html:
Here are two vectors representing the census years from 1900 to 1990 and the corresponding United States population in millions of people.
t = 1900:10:1990;
p = [75.995 91.972 105.711 123.203 131.669...
150.697 179.323 203.212 226.505 249.633];
The expression interp1(t,p,1975) interpolates within the census data to estimate the population in 1975. The result is
ans =
214.8585
- but I want to find the t value for 214.8585.
In some sense, you want to find roots of a function -
f(x)-val
First of all, there might be several answers. Second, since the function is piecewise linear, you can check each segment by solving the relevant linear equation.
For example, suppose that you have this data:
t = 1900:10:1990;
p = [75.995 91.972 105.711 123.203 131.669...
150.697 179.323 70.212 226.505 249.633];
And you want to find the value 140
val = 140;
figure;plot(t,p);hold on;
plot( [min(t),max(t)], [val val],'r');
You should first subtract the value of val from p,
p1 = p - val;
Now you want only the segments in which p1 sign changes, either from + -> -, or vice versa.
segments = abs(diff(sign(p1)==1));
In each of these segments, you can solve the relevant linear equation a*x+b==0, and find the root. That is the index of your value.
for i=1:numel(segments)
x(1) = t(segments(i));
x(2) = t(segments(i)+1);
y(1) = p1(segments(i));
y(2) = p1(segments(i)+1);
m = (y(2)-y(1))/(x(2)-x(1));
n = y(2) - m * x(2);
index = -n/m;
scatter(index, val ,'g');
end
And here is the result:
You can search for the value in Fa directly:
idx = Fa==value_to_find;
To find the index use find function:
find(Fa==value_to_find);
Of course, this works only if the value_to_find is present in Fa. But as I understand it, this is what you want. You do not need interp for that.
If on the other hand the value might not be present in Fa, but Fa is sorted, you can search for values larger than value_to_find and take the first such index:
find(Fa>=value_to_find,1);
If your problem is more complicated than that, look at Andreys answer.
Andrey's solution works in principle, but the code presented here does not. The problem is with the definition of the segments, which yields a vector of 0's and 1's, whereafter the call to "t(segments(i))" results in an error (I tried to copy & paste the code - I hope I did not fail in that simple task).
I made a small change to the definition of the segments. It might be done more elegantly. Here it is:
t = 1900:10:1990;
p = [75.995 91.972 105.711 123.203 131.669...
150.697 179.323 70.212 226.505 249.633];
val = 140;
figure;plot(t,p,'.-');hold on;
plot( [min(t),max(t)], [val val],'r');
p1 = p - val;
tn = 1:length(t);
segments = tn([abs(diff(sign(p1)==1)) 0].*tn>0);
for i=1:numel(segments)
x(1) = t(segments(i));
x(2) = t(segments(i)+1);
y(1) = p1(segments(i));
y(2) = p1(segments(i)+1);
m = (y(2)-y(1))/(x(2)-x(1));
n = y(2) - m * x(2);
index = -n/m;
scatter(index, val ,'g');
end
interpolate the entire function to a higher precision. Then search.
t = 1900:10:1990;
p = [75.995 91.972 105.711 123.203 131.669...
150.697 179.323 203.212 226.505 249.633];
precision = 0.5;
ti = 1900:precision:1990;
pi = interp1(t,p,ti);
now pi holds all pi values for every half a year. Assuming the values always increase you could find the year by max(ti(pi < x)) where x = 214.8585. Here pi < x creates a logical vector used to filter ti to only provide the years when p is less than x. max() is then used to take the most recent year, which will also be closest to x if the assumption that p is always increasing holds.
The answer to the most general case was given above by Andrey, and I agree with it.
For the example that you stated, a simple particular solution would be:
interp1(p,t,214.8585)
In this case you are solving for the year when a given population is known.
This approach will NOT work when there is more than one solution. If you try this with Andrey's values you will only get the first solution to the problem.

manipulating mathematical functions in matlab or any other language

Say I have a function
a = b / c
and I ask the user to input two of these variables, either b and a or c and a and I want it to calculate the unknown variable without needing to write a function for every variable
In this case I would use:
pseudo-code
if input is a & b
then c = b / a
if input is a & c
then b = a * c
if input is b & c
then a = b / c
I know this is a function with only three variables so it is easy to put it in an if-statement and voilà BUT I want to apply it to a system containing lots of equations (a jet engine for example). I used TkSolver before and it was really great, you throw as many equations as you want at it (a jet engine was an example!), you only need to give a number of known quantities and in a few seconds, all the unknowns are calculated (even if I had a known quantity in one side of the equation and unknown on another side mixed with known ones, it will do the maths!)
So, is there a way to do this in MatLab or perhaps python which I'm learning?
Edit to the question, thanks for directing me to use the Symbolic toolbox, it's great, I have another problem:
I couldn't think of a way to let the program know which of the variables is entered. I can do this:
syms f a b c
f = a * c - b %(I want to write a = b / c)
c = 10; a = 5;
X = eval(solve(f,b))
What I want now is a way of letting the user enter two knowns (e.g c & a) and the code will recognise them and solve to the unknown variable (e.g b).
Edit 2: I managed to get what I want, it's a bit long and there might be another way of achieving the same thing.
clear, clc
syms a b c
var = [{'a'}, {'b'}, {'c'}];
var1n = 0;
var2n = 0;
while isvarname(var1n) == 0
var1n = input('Which variable is known: ','s');
while ( any( strcmpi(var1n,var) ) )== 0
fprintf('\nThe variable entered is wrong, please enter a, b, or c')
var1n = input('\nWhich variable is known: ', 's');
end
end
fprintf('\nPlease enter the value of %s', var1n)
var1v = input(': ');
eval([var1n '=' num2str(var1v)]);
while isvarname(var2n) == 0
var2n = input('What is the second known variable: ', 's');
while ( any( strcmpi(var2n,var) ) ) == 0
fprintf('\nThe variable entered is wrong, please enter a, b, or c')
var2n = input('\nWhat is the second known variable: ', 's');
end
end
fprintf('\nPlease enter the value of %s', var2n)
var2v = input(': ');
eval([var2n '=' num2str(var2v)]);
var3n = char ( var ( find( strcmpi(var1n, var) == strcmpi(var2n, var) ) ) );
var3v = solve(a - b / c);
eval([var3n '=' char(var3v)]);
You could use this: http://www.mathworks.de/help/toolbox/symbolic/solve.html but you have to have the symbolic math toolbox (:
EDIT: On the documentation page of solve there's a sentence:
If the right side of an equation is 0, specify the left side as a
symbolic expression or a string:
That means, if you want to solve a = b/c for the value which is NOT set, simply rewrite the equation so that there is a zero on the right hand side:, i.e. a - b/c = 0, than you can use:
syms a b c
% E.g. assign values to a and c and automatically let matlab chose the 'free' variable (in this case, it's b:
a = input('Input var a: ')
a = input('Input var c: ')
solve(a - b/c)
which than gives you b (e.g. entering a = 10 and c = 40 gives you b = a * c = 400). Input function is explained here: http://www.mathworks.de/help/techdoc/ref/input.html! Hope that helps!

MATLAB simplification functions divide by common factors problem

I have a complicated expression H which is derived from several other complicated intermediate step. I want to get the [N D] = numden(H).
The problem is that the expression H, N and D is not being "evaluated" and they are also not simplified and divided by common factors.
I am using syms x.
For example, I get
H = (27+81*(x^2-987605098534947/1125899906842624*x-...
That is just so crazy.. but clearly,
H = (27+81*(x^2-0.8772*x-...
how can I get it to evaluate to simplest form?
Thanks in advance!
EDIT: I found out the closest bet is using VPA
My own workaround:
[num den] = numden(H)
num = vpa(num, 4);
den = vpa(den, 4);
H = num/den;
repeat from 1 until desired num and den are obtained.