I need to write a code to find numbers divisible by 7 and multiples of 5 from 1500:2700. How do I preallocate line 4 for speed and is my code the most efficient way to solve

18 visualizaciones (últimos 30 días)
result = [];
for num = 1500:2700
if mod(num, 7) == 0 && mod(num, 5) == 0
result = [result, num];
end
end
disp('Numbers between 1500 and 2700 that are divisible by 7 and multiples of 5:');
disp(result);
  4 comentarios
Umar
Umar el 12 de Sept. de 2024

Hi @Cade ,

You asked, “I need to write a code to find numbers divisible by 7 and multiples of 5 from 1500:2700. How do I preallocate line 4 for speed and is my code the most efficient way to solve”

Please see my response to your comments below.

After analyzing your code below,

result = [];
for num = 1500:2700
  if mod(num, 7) == 0 && mod(num, 5) == 0
      result = [result, num];
  end
end
disp('Numbers between 1500 and 2700 that are divisible by 7 and 
multiples of   
5:');
disp(result);

Your code is initializing an empty array result and appending qualifying numbers to it. However, dynamically resizing arrays in MATLAB can be inefficient due to memory reallocation during each append operation and I do concur with @dpb comments.

Here is my recommendations for improvement mentioned below.

Preallocation: Preallocate the array to avoid repeated resizing. Since you know the range (1500 to 2700), you can estimate the maximum number of elements that will be added. The total count of integers in this range is 201, but not all will meet your criteria.

Efficient Filtering: Instead of checking each number individually, you can create a vector of numbers that are multiples of both 7 and 5 directly.

Algorithm Optimization: To find numbers divisible by both 7 and 5, you can calculate their least common multiple (LCM), which is 35. This allows you to iterate only through multiples of 35.

Here’s a refined version of your code with preallocation:

% Preallocate result array assuming a rough upper limit
max_size = floor((2700 - 1500) / 35) + 1; % Estimate upper limit based   on LCM
result = zeros(1, max_size); % Preallocate with zeros
index = 1; % Index for result array
for num = 1500:2700
  if mod(num, 35) == 0 % Check divisibility by LCM of 7 and 5
      result(index) = num; % Store number in preallocated array
      index = index + 1; % Increment index for next entry
  end
end
% Trim result array to actual size
result = result(1:index-1); 
disp('Numbers between 1500 and 2700 that are divisible by 7 and 
multiples of 
5:');
disp(result);

Please see attached.

So, in the refined code above, the result array is now preallocated with an estimated size based on the number of expected valid entries. It checks for mod(num, 35) == 0, reducing the number of checks needed. An index variable keeps track of where to insert new numbers into the preallocated array, making sure no empty slots remain at the end.

Please let me know if you have any further questions.

DGM
DGM el 12 de Sept. de 2024
There's no harm in using non-critical tasks like homework to learn different ways to solve a given problem. As dpb alluded:
% we have a vector of all candidate numbers
candidates = 1500:2700;
%% we could solve the problem using a loop
% i'm not going to address the issue of preallocation
% dpb already touched on that
% we're just using this as a reference
result = []; % initialize
for k = 1:numel(candidates)
if mod(candidates(k), 7) == 0 && mod(candidates(k), 5) == 0 % scalar AND
result = [result candidates(k)]; % we could fix this, but i'm ignoring that
end
end
%% or we could do it without the loop
% we have two logical vectors of equal length
% combined into one using a basic boolean operator
mask = mod(candidates,5) == 0 & mod(candidates,7) == 0; % elementwise AND
% logical arrays can be used for indexing into arrays
selected = candidates(mask);
% compare the results
isequal(result,selected)
ans = logical
1
That said, I don't know whether you've been told explicitly to use a loop. If so, @dpb suggested a way to use overallocation.

Iniciar sesión para comentar.

Respuestas (2)

Sameer
Sameer el 12 de Sept. de 2024
Editada: Sameer el 12 de Sept. de 2024
Hi cade
To improve the efficiency of your code, you can preallocate the "result" array to its expected size before entering the loop. This avoids dynamically resizing the array during each iteration.
Here's how you can modify your code to preallocate the "result" array:
% Preallocate the result array with an estimated size
result = zeros(1, floor((2700 - 1500) / 35) + 1); % 35 is the LCM of 7 and 5
index = 1; % Initialize an index variable
for num = 1500:2700
if mod(num, 7) == 0 && mod(num, 5) == 0
result(index) = num;
index = index + 1;
end
end
% Trim the result array to the correct size
result = result(1:index-1);
disp('Numbers between 1500 and 2700 that are divisible by 7 and multiples of 5:');
disp(result);
Hope this helps!

John D'Errico
John D'Errico el 12 de Sept. de 2024
Editada: John D'Errico el 12 de Sept. de 2024
Lol. A huge amount of traffic on this from last night when I looked in. But you did write code. So how would I solve the problem? I might not even bother to use an explicit loop at all. Consider these variations.
First, a scheme we might consider if we think about the Sieve of Eratosthenes, where we flag elements as being of interest or not. I'll need to use preallocation. In the end, I have flagged multiples of 5 and 7, by adding a 1 to the vector. So a multiple of both 5 and 7 should have the number 2 in the corresponding location.
v = zeros(1,2700 - 1500 + 1);
v(1:5:end) = 1;
offset7 = 7 - mod(1500,7) + 1; % add 1 here, since MATLAB has an index origin of 1.
v(offset7:7:end) = v(offset7:7:end) + 1;
x1 = find(v == 2) + 1500 - 1
x1 = 1x35
1505 1540 1575 1610 1645 1680 1715 1750 1785 1820 1855 1890 1925 1960 1995 2030 2065 2100 2135 2170 2205 2240 2275 2310 2345 2380 2415 2450 2485 2520
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Personally, that seems a bit kludgy. I had to preallocate, then I had to worry about various offsets, dealing with the MATLAB index origin. And I had to use find at the end. But it avoids an explicit loop.
Next, consider how to use the intersect function.
% using the function intersect, which computes the
% intersection of two sets of numbers.
firstMultipleOf7 = 1500 + 7 - mod(1499,7);
x2 = intersect(1500:5:2700,firstMultipleOf7:7:2700)
x2 = 1x35
1505 1540 1575 1610 1645 1680 1715 1750 1785 1820 1855 1890 1925 1960 1995 2030 2065 2100 2135 2170 2205 2240 2275 2310 2345 2380 2415 2450 2485 2520
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Cute, huh? Intersect is a nice tool when it comes up. Just be careful, as too many users think intersect finds the intersectino of lines, or something like that. Intersect is a tool that works with sets.
Next, we might consider that a number that is both a multiple of 5 and of 7, is a inevitably a multiple of 35. So we can create the set of numbers we want directly.
firstMultipleOf35 = 1500 + 35 - mod(1499,35)
firstMultipleOf35 = 1505
x3 = firstMultipleOf35:35:2700
x3 = 1x35
1505 1540 1575 1610 1645 1680 1715 1750 1785 1820 1855 1890 1925 1960 1995 2030 2065 2100 2135 2170 2205 2240 2275 2310 2345 2380 2415 2450 2485 2520
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Seriously, if we are looking for a maximally efficient scheme, that would seem to be it, or at least likely the best I can do. Too bad, as the final solution is rather boring. A more interesting variation of this question would have been to list the integers that are divisible by 5, but NOT by 7 in that interval. You might think about how you would have solved that variation.

Categorías

Más información sobre Loops and Conditional Statements en Help Center y File Exchange.

Etiquetas

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by