Smallest integer greater than or equal to harmonic series of input - matlab

I'm working on the following problem:
I realize my code is a bit off, but I want to create a for loop that will determine whether or not the integer x (the input value) is at least less than or equal to the sum of a harmonic series.
Here is what I have so far:
function n =one_per_n(x)
if x > 10000
n = -1;
end
total = 0;
i = 0;
for i = 1:10000
if x >= total
n = ceil(total);
else
total = (1/i) + total;
end
end
I've added my attempt at a while loop. I realize it's wrong, but any help would be appreciated.
function n =one_per_n(x)
if x > 10000
n = -1;
end
total = 0;
i = 0;
for i = 1:10000
while total <= x
total = (1/i) + total;
end
end
n = total;

you don't need to use some loops:
function n = one_per_n(x)
lim = min(10000,exp(x));
value = cumsum(1./(1:lim));
n = find(value >= x,1);
if isempty(n)
n = -1;
end

A while loop is a better option in this case I think
function [total, n] = one_per_n(x)
% This is a good initial check, good work
if x > 10000
n = -1;
return;
end
% Initialize the variables
total = 0;
n = 0;
% While not finished
while (total < x)
% Number of terms
n = n + 1;
total = total + 1/n;
end
end

Related

Possible errors in a code at matlab about a function

Let Sn = 8Σ (1/((4κ-3)(4κ-1))). It is known that lim of Sn when n tends to infinitive is equal to pi.
Write a function [sn,n] = mySumPi(tol) which outputs Sn and n for the smallest n such that absolute value of Sn-pi
I have written the following code but it seems that it does not work.
function [sn,n] = mySumPi(tol)
%[sn,n] = mySumPi(tol)
%lim as n approaches infinity is pi
% n is the smallest numbers such that the abs(sn-pi) <tol
count = 0;
sn=0
while abs(sn-pi) >= tol
sn = sn + (8*sn)*(((4*n)-3)*((4*n)-1))
count = count+1;
n = count - 1;
end
end
I think you can try the code below.
function [sn,n] = mySumPi(tol)
n = 1;
sn = 0;
while 1 % repeat the procedure until the termination condition is valid
sn = sn + 8/(((4*n)-3)*((4*n)-1)); % you had wrong formula in you code
if abs(sn-pi) < tol % termination condition
break;
else
n = n + 1;
end
end
end
such that
>> [sn,n] = mySumPi(1e-1)
sn = 3.0418
n = 5
>> [sn,n] = mySumPi(1e-3)
sn = 3.1406
n = 500
>> [sn,n] = mySumPi(1e-5)
sn = 3.1416
n = 50000

Matlab Nested Radicals

Working on an assignment in MATLAB and I can't seem to figure this problem out due to the arithmetic, I've been trying it for about 6 hours now
I need to create a loop that accepts user input > 1 (done) and loops through the following (m is input)
t1 = sqrt(m);
t2 = sqrt(m-sqrt(m));
t3 = sqrt(m-sqrt(m+sqrt(m)))
t4 = sqrt(m-sqrt(m+sqrt(m-sqrt(m))))
t5 = sqrt(m-sqrt(m+sqrt(m-sqrt(m+sqrt(m)))))
and so on until the new t value minus the old t value is < 1e-12
My current code is as follows
%Nested Radicals
clear all;
clc;
%User input for m
m = input('Please enter a value for m: ');
%Error message if m is less than 1
if m <= 1
fprintf('ERROR: m must be greater than 1\n')
m = input('Please enter a value for m: ');
end
%Error message if m is not an integer
if mod(m,1) ~= 0
fprintf('m must be an integer\n')
m = input('Please enter a value for m: \n');
end
%Nested things
t_old = m;
t_new = sqrt(m);
varsign = -1;
index = 1;
loop = true;
endResult = 1e-12;
sqrts = [sqrt(m), sqrt(m-sqrt(m)), sqrt(m-sqrt(m+sqrt(m))), sqrt(m-sqrt(m+sqrt(m-sqrt(m)))), sqrt(m-sqrt(m+sqrt(m-sqrt(m+sqrt(m)))))];
fprintf('m = %d\n',m)
fprintf('t1 = %14.13f\n', t_new')
while loop
if index ~= 1
curResult = abs(sqrts(1,index) - sqrts(1, index-1));
else
curResult = abs(sqrts(1, index));
end
if curResult > endResult
if index < 5
t_new = sqrts(1, index+1);
else
t_new = sqrts(1, index);
loop=false;
end
if index
fprintf('t%d = %14.13f\n', index, t_new)
end
else
fprintf('t%d = %14.13f\n', index, t_new);
break;
end
index = index + 1;
if index > 50
fprintf('t%d = %14.13f\n', index, t_new);
break;
end
end
Unless I'm very much mistaken, you can write the expression for t(n) as follows:
t(n) = sqrt(m-sqrt(m+t(n-2));
which makes it a lot easier to loop:
%Nested Radicals
clear all;
clc;
%User input for m
m = input('Please enter a value for m: ');
%Error message if m is less than 1
if m <= 1
fprintf('ERROR: m must be greater than 1\n')
m = input('Please enter a value for m:');
end
%Error message if m is not an integer
if mod(m,1) ~= 0
fprintf('m must be an integer\n')
m = input('Please enter a value for m:');
end
%Nested things
t_old = sqrt(m);
t_new = sqrt(m-sqrt(m));
threshold = 1e-12;
k = 3;
while abs(t_new - t_old) >= threshold
temp = sqrt(m-sqrt(m+t_old));
t_old = t_new;
t_new = temp;
k = k+1;
end
fprintf('t%d = %14.13f\n', k-2, t_old);
fprintf('t%d = %14.13f\n', k-1, t_new);
fprintf('t%d - t%d = %14.13f\n', k-2, k-1, t_old - t_new);
which gives for m=9 for example:
Please enter a value for m: 9
t17 = 2.3722813232696
t18 = 2.3722813232691
t17 - t18 = 0.0000000000005
I'm not sure what you're trying to do with the sqrts variable, you should be calculating each step on the fly in your loop, since you can't possibly know how deep you need to go
m = 5; % Get m however you want to
n = 0; % Iteration counter
tol = 1e-12 % Tolerance at which to stop
dt = 1; % initialise to some value greater than 'tol' so we can start the loop
% Loop until tn is less than tolerance. Would be sensible to add a condition on n,
% like "while tn > tol && n < 1000", so the loop doesn't go on for years if the
% condition takes a trillion loops to be satisfied
while dt > tol
% Set the value of the deepest nested expression
tn = sqrt(m);
% We know how many times take sqrt, so for loop our way out of the nested function
% Initially we want the sign to be -1, then +1, -1, ...
% This is achieved using ((-1)^ii)
for ii = 1:n
tn = sqrt(m + ((-1)^ii)*tn); % Calculate next nested function out
end
% Increment iteration number
n = n + 1;
dt = abs( t_old - tn );
t_old = tn;
end
I've not done any analysis on your function, so have no idea if it's guaranteed to converge to some value <1e-12. If it isn't then you definitely need to add some maximum iteration condition as I suggest in the comments above.

Matlab loop not working properly

largest = 0;
num = 0;
temp = 0;
num_flip = 0;
for x = 100 : 999
for y = x : 999
num = x*y;
temp = num2str(num);
num_flip = str2double(fliplr(temp));
if num/num_flip == 1
largest = num;
one = x;
two = y;
end
end
end
I'm trying to find the largest palindrome made from the product of two 3-digit numbers but for some reason my the loop stops at x = 924 and y = 962 but I know that's not answer. The code works fine for 2-digit numbers(10 : 99) though.
You are not testing if largest is truly the largest with that code. As you go through the loops it is possible that a smaller palindrome will be detected after a larger one, and you are reassigning largest to it.
Try this with an added test for whether a new palindrome is larger than the current largest:
largest = 0;
num = 0;
temp = 0;
num_flip = 0;
for x = 100 : 999
for y = x : 999
num = x*y;
temp = num2str(num);
num_flip = str2double(fliplr(temp));
if ((num/num_flip) == 1) && (num > largest)
largest = num;
end
end
end
I removed these assignments
one = x;
two = y;
because it's not clear what they are for from your question. Add them back if they are needed for a reason not shown.

Multiplying a vector by random numbers while keeping the sum the same (MATLAB)

I'm trying to multiply (element wise) a vector V of length N by a randomly generated number in the range (a,b), while keeping the sum of the vector equal to a total amount, E. I want to do this in MATLAB, but I'm not sure how. Getting random numbers between a certain range I know how to do:
minrand = 0;
maxrand = 1;
randfac = (maxrand-minrand).*rand(1,N) + minrand;
But yeah, beyond that I'm pretty clueless. I guess the random numbers can't really be generated like this, because if we call the random numbers the vector R, then I want that
R_1*V1 + R_2*V2 .... + R_N*V_N = E. So I guess it's a big equation. Is there any way to solve it, while putting constraints on the max and min values of R?
You can pick pairs of two elements (in all combinations) and add and subtract an equal random number.
% Make up a random vector
N=10;
randfac = 10*rand(1,N);
%OP Answer here: Given randfac with sum E re-randomize it
E = sum(randfac);
minrand = 0;
maxrand = 2;
disp(randfac)
% v = [6.4685 2.9652 6.6567 1.6153 7.3581 0.0237 7.1025
% 3.2381 1.9176 1.3561]
disp(sum(randfac))
% E = 38.7019
r = minrand + (maxrand-minrand)*rand(N*N,1);
k = 1;
for i=1:N
for j=1:N
randfac(i) = randfac(i)-r(k);
randfac(j) = randfac(j)+r(k);
k = k + 1;
end
end
disp(randfac)
% v = [5.4905 0.7051 4.7646 1.3479 9.3722 -1.4222 7.9275
% 7.5777 1.7549 1.1836]
disp(sum(randfac))
% E = 38.7019
Just divide the vector with the sum and multiply with the target E.
randfac = (maxrand-minrand).*rand(1,N) + minrand;
randfac = E*randfac/sum(randfac);
as long as the operator is linear, the result is going to retain it's randomness. Below is some sample code:
minrand = 0;
maxrand = 1;
N = 1000; %size
v = (maxrand-minrand).*rand(1,N) + minrand;
E = 100; %Target sum
A = sum(v);
randfac = (E/A)*v;
disp(sum(randfac))
% 100.0000
First of all with random numbers in the interval of [a b] you can't guarantee that you will have the same summation (same E). For example if [a b]=[1 2] of course the E will increase.
Here is an idea, I don't know how random is this!
For even N I randomize V then divide it in two rows and multiply one of them with random numbers in [a b] but the second column will be multiplied to a vector to hold the summation fixed.
N = 10;
V = randi(100,[1 N]);
E = sum(V);
idx = randperm(N);
Vr = V(idx);
[~,ridx] = sort(idx);
Vr = reshape(Vr,[2 N/2]);
a = 1;
b = 3;
r1 = (b - a).*rand(1,N/2) + a;
r2 = (sum(Vr) - r1.*Vr(1,:))./Vr(2,:);
r = reshape([r1;r2],1,[]);
r = r(ridx);
Enew = sum(V.*r);
The example results are,
V = [12 82 25 51 81 51 31 87 6 74];
r = [2.8018 0.7363 1.9281 0.5451 1.9387 -0.4909 1.3076 0.8904 2.9236 0.8440];
with E = 500 as well as Enew.
I'm simply assigning one random number to a pair (It can be considered as half random!).
Okay, I have found a way to somewhat do this, but it is not elegant and there are probably better solutions. Starting with an initial vector e, for which sum(e) = E, I can randomize its values and end up with an e for which sum(e) is in the range [(1-threshold)E,(1+thresholdE)]. It is computationally expensive, and not pretty.
The idea is to first multiply e by random numbers in a certain range. Then, I will check what the sum is. If it is too big, I will decrease the value of the random numbers smaller than half of the range until the sum is no longer too big. If it is too small, I do the converse, and iterate until the sum is within the desired range.
e = somepredefinedvector
minrand = 0;
maxrand = 2;
randfac = (maxrand-minrand).*rand(1,N) + minrand;
e = randfac.*e;
threshold = 0.001;
while sum(e) < (1-threshold)*E || sum(e) > (1+threshold)*E
if sum(e) > (1+threshold)*E
for j = 1:N
if randfac(j) > (maxrand-minrand)/2
e(j) = e(j)/randfac(j);
randfac(j) = ((maxrand-minrand)/2-minrand).*rand(1,1) + minrand;
e(j) = randfac(j)*e(j);
end
if sum(e) > (1-threshold)*E && sum(e) < (1+threshold)*E
break
end
end
elseif sum(e) < (1-threshold)*E
for j = 1:N
if randfac(j) < (maxrand-minrand)/2
e(j) = e(j)/randfac(j);
randfac(j) = (maxrand-(maxrand-minrand)/2).*rand(1,1) + (maxrand-minrand)/2;
e(j) = randfac(j)*e(j);
end
if sum(e) > (1-threshold)*E && sum(e) < (1+threshold)*E
break
end
end
end
end

Simon Funk vs. Matlabs SVDS

I want to build an recommender system using Simon Funks' algorithm.
The idea is to first construct the model offline in Matlab to perform some evaluation on the results to what number of features (or dimensions) gives the best performance.
I have a matrix with users x items, where the rating '0' means that the user has not given a rating for that item.
So far I have tried to implement Simon Funks' algorithm in Matlab (see source-code) below, but it performs really (!) bad. By accident I found Matlab's SVDS function to fill the empty ratings and it actually performs better and faster then my Simon Funks' function
Could someone tell me what could be cause of this? Or tell me what stupid mistake I have made in Matlab function? :P
function ratings = simon_funk(original_ratings, dimensions) % To construct a complete rating matrix
% See: http://www.timelydevelopment.com/demos/NetflixPrize.aspx
% Variables
global max_features; max_features = dimensions;
global init; init = 0.1;
min_epochs = 2;
max_epochs = 16;
min_improvement = 0.001;
lrate = 0.01;
k = 0.015;
respondent_count = size(original_ratings, 1);
item_count = size(original_ratings, 2);
rating_count = 0;
data = [];
for r=1:respondent_count
for i=1:item_count
rating = original_ratings(r,i);
if(rating > 0)
data = [data; [r, i, rating, 0]];
rating_count = rating_count + 1;
end
end
end
% Now data contain all ratings in the form [user_id, item_id, rating, cache (default 0)]
ratings = zeros(respondent_count, item_count);
global item_features; item_features = zeros(max_features, item_count);
global respondent_features; respondent_features = zeros(max_features, respondent_count);
% Init
item_features(:,:) = init;
respondent_features(:,:) = init;
% CalcFeatures
rmse_last = 2.0;
rmse = 2.0;
for f=1:max_features
for e=1:max_epochs
sq = 0;
rmse_last = rmse;
for r=1:rating_count
% for i=1:item_count
respondent = data(r,1);
item = data(r,2);
rating = data(r,3);
% Predict rating
p = simon_funk_predict_rating(data(r,:), f, 1);
err = (1.0 * rating - p);
sq = sq + err*err;
rf = respondent_features(f,respondent);
mf = item_features(f, item);
% Cross-train the features
respondent_features(f, respondent) = respondent_features(f,respondent) + (lrate * (err * mf - k * rf));
item_features(f, item) = item_features(f, item) + (lrate * (err * rf - k * mf));
% end
end
rmse = sqrt(sq/rating_count);
%if (e >= min_epochs && rmse > (rmse_last - min_improvement))
if ((e >= min_epochs) && ((rmse_last - rmse) < min_improvement))
break;
end
end
% Caching
for r=1:rating_count
data(r, 4) = simon_funk_predict_rating(data(r,:), f, 0);
end
end
% return new ratings set
for r=1:respondent_count
for i=1:item_count
sum = 1;
for f=1:max_features
sum = sum + item_features(f,i) * respondent_features(f,r);
if(sum > 10)
% sum = 10;
end
if(sum < 1)
% sum = 1;
end
end
ratings(r,i) = sum;
end
end
And the function to predict an individual rating:
function sum = simon_funk_predict_rating(rating, f, bTrailing)
global item_features;
global respondent_features;
global max_features;
global init;
respondent = rating(1,1);
item = rating(1,2);
cache_value = rating(1,4);
sum = 1;
if(cache_value > 0)
sum = cache_value;
end
sum = sum + (item_features(f,item) * respondent_features(f,respondent));
if (sum > 10)
%sum = 10;
end
if (sum < 1)
%sum = 1;
end
if (bTrailing == 1)
sum = sum + (max_features - f - 1) * (init * init);
if (sum > 10)
sum = 10;
end
if (sum < 1)
sum = 1;
end
end
Thank you very much!