Compare symbolic variables - matlab

I am trying to compare two symbolic variables (numbers). The whole problem boils down to the following code.
R = vpa(0.555555555555555555555555555);
isAlways(R>R*(1-sym(10^(-10))))
isAlways(R>R*(1-sym(10^(-50))))
Both comparisons should return 1, but the second returns 0.
My solution:
digits(51);
R = vpa(0.555555555555555555555555555);
isAlways(R>R*(1-sym(10^(-10))))
isAlways(R>R*(1-sym(10^(-50))))

Why you encounter this problem
vpa evaluates symbolic inputs with variable-precision floating-point arithmetic (32 significant digits by default)... So what's happening in your case is
>> R = vpa(0.555555555555555555555555555)
R =
0.55555555555555555555555555555556
>> R*(1-sym(10^(-50)))
ans =
0.55555555555555555555555555555556
32 digits are definitely not enough to store the actual value of 1-10^(-50).
How to fix it
Without stressing with vpa() you can declare both R and R * (1 - 10^(-50)) as symbolics (in fact 0.5555555... = 5/9), and compare them:
>> R = str2sym('5/9');
>> X = str2sym('5/9 * (1 - 10^(-50))');
>> isAlways(R > X)
ans =
logical
1

Related

Matlabs "splitapply" used on functions with multiple parameters

I don't understand matlabs splitapply function:
>> f=#(t,x) sum(sum(t),sum(x))
f =
function_handle with value:
#(t,x)sum(sum(t),sum(x))
>> splitapply(f,[1,0;0,0],[1,1;2,2],1:2)
ans =
1 0
I expected the two matrices to be split into columns and the two first columns fed to f, resulting in a total sum of 4=(1+0)+(1+2). Then both the second columns should be fed to f, resulting in the number 3=(0+0)+(1+2).
So I expected
ans =
4 3
But quite obviously that is not what happend. And I am not sure why. If I use splitapply on functions with only one argument, it seems to do what I expect:
>> splitapply(#sum,[1,1;2,3],1:2)
ans =
3 4
I would be glad if someone could point out what is happening. This is the documentation if someone else can understand it better than me: https://de.mathworks.com/help/matlab/ref/splitapply.html
You probably want
f = #(t,x) sum([sum(t) sum(x)])
or
f = #(t,x) sum(t)+sum(x)
rather than
f = #(t,x) sum(sum(t), sum(x))
The latter is interpreted as compute the sum of sum(t) along the dimension given by sum(x).
With this correction,
>> f = #(t,x) sum([sum(t) sum(x)]);
>> splitapply(f,[1,0;0,0],[1,1;2,2],1:2)
ans =
4 3

Mod function returns 0 for Matlab

I have a problem with the mod function output in Matlab. I am trying to perform some calculations for ECC double and add algorithm. I am reading data from a file and storing it in a variable and then performing some operations. All works smoothly except that I get 0 in temp1 when I use mod(X2,P). However if I put in values stored in X2(3.0323e+153) and P(1.1579e+77) on command window (mod( 3.0323e+153, 1.1579e+77)), I get the correct values. Can anyone please help me? Below is the part of script which is problematic.
P = hex2dec('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
line = fread(fileID,[1,67],'*char');
while ~feof(fileID)
PX = line(4:67);
X = hex2dec(PX);
X2 = X^2;
temp1= mod(X2 , P)
end
line = fread(fileID,[1,69],'*char');
end
fclose(fileID);
I think the problem lies with how you're initializing P. From the documentation for hex2dec (emphasis mine):
d = hex2dec('hex_value') converts hex_value to its floating-point integer representation. The argument hex_value is a hexadecimal integer stored as text. If the value of hex_value is greater than the hexadecimal equivalent of the value returned by flintmax, then hex2dec might not return an exact conversion.
And the value of flintmax is:
>> flintmax
ans =
9.007199254740992e+15
Quite a bit smaller than your value for P. In fact, if we use num2hex to look at the two ways you initialize P, you can see a clear difference:
>> P = hex2dec('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
>> num2hex(P)
ans =
4ff0000000000000
>> num2hex(1.1579e+77)
ans =
4fefffda293c30de
As it turns out, the inexact conversion done by hex2dec results in a number that evenly divides into 3.0323e+153, thus giving you a remainder of 0:
>> mod(3.0323e+153, P)
ans =
0
>> mod(3.0323e+153, 1.1579e+77)
ans =
8.795697942083107e+76

Displaying rational numbers in Matlab

I have two integer numbers m,n which together form a rational number in the form of m/n. Now I just want to display them in Matlab in this rational form.
I can do this by doing
char(sym(m/n))
So, if, e.g. m = 1, n = 2, Matlab will display 1/2. However, if m = 2, n = 4, I am also getting 1/2, whereas I want to get 2/4.
Any way of doing this without recurring to something like
fprintf( '%d/%d', m, n )
Thanks
You can change the display format to rat
>> format rat
>> 2/3
ans =
2/3
otherwise you can call rats function
>> rats(2/3)
ans =
2/3
>> class(ans)
ans =
char
However, in both cases the fractions will be reduced. To avoid that you should create your separate function or introduce it as an anonymous function
>> rat2 = #(m,n) num2str([m n], '%d/%d')
rat2 =
#(m,n)num2str([m,n],'%d/%d')
>> rat2(2,4)
ans =
2/4

Summation of sines with limits and a variable?

I need help to add a function, from 1 to 10, using MATLAB. The function is ((1/n)*sin(n*pi*x)) where n goes from 1 to 10 and x stays as a variable. Ultimately I want to have a summation of ten sines (i.e K1*sin(pi*x)+K2*sin(2*pi*x)+k3*sin(3*pi*x)+...etc) where k is a constant. I would really appreciate any assistance. Thanks
Edit: Thanks to everyone who helped with my problem However I should have been more specific when asking my question. After getting the summation, I want to plot the sine series. I tried doing this but I kept getting an error saying that "conversion from sym to double is not possible" Now I tried doing a for loop to get my graph. My code is as follows:
n = 0:10;
while i <= n
for i = 1:length(n);
T = (1/n(i))*sin(n(i)*pi*x);
end
i = 1+i;
max = sum(T);
end
plot(x,max,'black')
However this doesn't work. I don't think that this is the proper way to get the sum of a double. I would really appreciate it if someone could help me again. Thanks again
Learn to exploit MATLAB's vector nature.
For one-off shots:
>> f = #(n,x) sin((1:n)*pi*x) * (1./(1:n).');
>> f(200, 0.5)
ans =
7.828982258896381e-001
To be able to evaluate f(n,x) with vector/matrix input x:
>> f = #(n,x) reshape( sin( bsxfun(#times, (1:n)*pi, x(:)) ) * (1./(1:n).'), size(x) );
>> f(15,rand(2))
ans =
5.077194963950054e-001 2.660834723822258e-001
1.416130930552744e+000 1.012255979042172e-001
Replace (1./(1:n).') by [K1 K2 K3 ...].' when you want to use other constants than 1/n.
From my understanding you are trying to sum the multivariable expression. In your case, you have two variables n and x. You want to sum the expression from n = 1 to 10 keeping x as a variable. You can do this in MATLAB by using symsum function, whose syntax is
symsum(expr,var,a,b)
Where expression expr defines the terms of a series, with respect to the symbolic variable var. The value of the variable var changes from a to b. If you do not specify the variable, symsum uses the default variable determined by symvar. If expr is a constant, then the default variable is x.
So in your case
expr = (1/n*sin(n*pi*x)
var = n
a = 1
b = 10
The simple code would be
>>syms n x
>>F = symsum ((1/sym('n'))*sin(sym('n')*pi*x), n, 1, 10)
Answer to Edit: MATLAB cannot convert the sys variable to double. You can instead substitute the value of sym variable with variable from MATLAB workspace. For example you can plot the above function for the range 0 to 10 by using following command.
>> x = 0:0.1:10;
>> plot(x, subs(F))

Stability (Numerical analysis)

I'm trying to find the max machine number x that satisfies the following equation: x+a=a, where a is a given integer. (I'm not allowed to use eps.)
Here's my code (which is not really working):
function [] = Largest_x()
a=2184;
x=0.0000000001
while (x+a)~=a
x=2*x;
end
fprintf('The biggest value of x in order that x+a=a \n (where a is equal to %g) is : %g \n',a,x);
end
Any help would be much appreciated.
The answer is eps(a)/2.
eps is the difference to the next floating point number, so if you add half or less than that to a float, it won't change. For example:
100+eps(100)/2==100
ans =
1
%# divide by less than two
100+eps(100)/1.9==100
ans =
0
%# what is that number x?
eps(100)/2
ans =
7.1054e-15
If you don't want to rely on eps, you can calculate the number as
2^(-53+floor(log2(a)))
You're small algorithm is certainly not correct. The only conditions where A = X + A are when X is equal to 0. By default matlab data types are doubles with 64 bits.
Lets pretend that matlab were instead using 8 bit integers. The only way to satisfy the equation A = X + A is for X to have the binary representation of [0 0 0 0 0 0 0 0]. So any number between 1 and 0 would work as decimal points are truncated from integers. So again if you were using integers A = A + X would resolve to true if you were to set the value of X to any value between [0,1). However this value is meaningless because X would not take on this value but rather it would take on the value of 0.
It sounds like you are trying to find the resolution of matlab data types. See this: http://www.mathworks.com/help/matlab/matlab_prog/floating-point-numbers.html
The correct answer is that, provided by Jonas: 0.5 * eps(a)
Here is an alternative for the empirical and approximate solution:
>> a = 2184;
>> e = 2 .^ (-100 : 100); % logarithmic scale
>> idx = find(a + e == a, 1, 'last')
idx =
59
>> e(idx)
ans =
2.2737e-013