2 votos

Matlab: Bucle while en función

Soy nuevo en Matlab (y también en stackexchange) y necesito aprenderlo para una clase de Macro dinámica.

Tengo problemas para utilizar un bucle while en una función. Se supone que la función debe calcular la cantidad de monedas que uno necesita para pagar el precio p. Sin embargo, mi función sólo proporciona un vector que muestra las monedas que necesito y no la cantidad de las mismas. Espero que alguien intervenga y me ayude a salir de mi problema. Aquí está mi código:

function[c] = achange(p,coins)
s=size(coins);  
c=zeros(1,s(2)); 

while p>0
    for i=1:s(2) 
    if coins(i) <= p 
        p=p-coins(i); 
        c(i)=c(i)+1; 
    end
    end
end 
end

0 votos

Vale, pues deberías saber que el stackexchange de economía es para preguntas de economía, no de Matlab.

0 votos

@user253751 no en realidad nuestro centro de ayuda dice explícitamente: "Preguntas sobre software: Las preguntas relacionadas con el software utilizado en economía y econometría, son on-topic aquí." Ver aquí . Así que esta pregunta es totalmente en el tema porque es la aplicación de matlab a alguna pregunta de economía. Matlab se utiliza mucho en la economía para la modelización numérica - No reconozco el tipo de problema de arriba, ya que no está conectado a nada de lo que me especializo, pero parece un problema de Economía

2 votos

Su función parece estar bien. Supongamos que el bien cuesta 60 céntimos, y que tienes el siguiente vector de monedas $(1,2,5,10,20)$ entonces la función devuelve $(4,3,2,2,1)$ diciéndole que necesita 4 monedas de un céntimo, 3 de dos céntimos, etc., que suman 60 céntimos, que es el precio del bien.

2voto

user23117 Puntos 1292

Pensé un poco en el problema, y se me ocurrió el siguiente hack rápido, que parece funcionar.

Aquí está el trozo de código que debería hacer el trabajo en principio con enteros:

function  [exch]=achange(p,coins)
s=size(coins);
c=zeros(1,s(2));
coins=sort(coins,'descend');
it=1:s(2);
isaninteger = @(x)isfinite(x) & x==floor(x);
if p<coins(end)
   return
end
if isaninteger(p)==0
   exch.coins=coins;
   exch.c=inf(1,s(2));
   exch.rest=inf;
   return
elseif any(isaninteger(coins)==0)
   exch.coins=coins;
   exch.c=inf(1,s(2));
   exch.rest=inf;
   return
end
rest=0;
while p>0
    trQ=mod(p,coins)==0;
    idx=it(trQ);
    li=length(idx);
    if isempty(idx)
       rst=1;
       rest=rest+rst;
       p=p-rst;
    elseif li>0 && li<s(2)
      ps=it(trQ)==0;
      idx2=idx;
      idx2(ps)=[];
      for k=1:li
          if p>0
             p=p-coins(idx2(k));
             c(idx2(k))=c(idx2(k))+1;
          end
      end
    elseif li==s(2)
     for k=1:li
         if p>0
            p=p-coins(idx(k));
            c(idx(k))=c(idx(k))+1;
         end
     end
    end
end
exch.coins=coins;
exch.c=c;
exch.rest=rest;
end

Al menos para el siguiente ejemplo funciona:

>> exch=achange(57,[10 25])
exch = 
struct with fields:
  coins: [25 10]
      c: [1 2]
   rest: 12

>> exch.coins*exch.c' + exch.rest
ans =
57

o para:

>> exch=achange(51,[10 25])
exch = 
struct with fields:
    coins: [25 10]
        c: [1 2]
     rest: 6

>> exch.coins*exch.c' + exch.rest
ans =
51

y finalmente mi ejemplo de los comentarios:

>> exch=achange(60,[1 2 5 10 20])
exch = 
    struct with fields:
    coins: [20 10 5 2 1]
        c: [1 1 3 4 7]
     rest: 0

>> exch.coins*exch.c'  
ans =
60

Si alguna entrada no es un número entero, obtenemos

>> exch=achange(57,[5 .10 25])
exch = 
    struct with fields:
    coins: [25 5 0.1000]
        c: [Inf Inf Inf]
    rest: Inf

o similar

>> exch=achange(57.8,[5 10 25])
exch = 
   struct with fields:
     coins: [25 10 5]
         c: [Inf Inf Inf]
      rest: Inf

ACTUALIZACIÓN 21.11.2020

Debido al hecho de que la asignación de las especies no es óptima por el código anterior, que se puede ver, por ejemplo, por el primer ejemplo, donde la cantidad residual todavía se puede asignar a algunas monedas, proporciono una pequeña enmienda que debe producir mejores resultados.

El importe residual del ejemplo mencionado es $12$ indicando que la estructura del problema no cambia, lo que nos permite resolver el problema recursivamente. Es decir, debemos sustituir las líneas de código después del bucle While por la siguiente construcción If para invocar una llamada recursiva siempre que sea necesario.

if any(rest>coins)
   exch2=achange(rest,coins);
   exch.coins=coins;
   exch.c=c+exch2.c;
   exch.rest=exch2.rest;
else
   exch.coins=coins;
   exch.c=c;
   exch.rest=rest;
end   

Entonces podemos reducir la cantidad residual del primer ejemplo de $12$ a $2$ como podemos ver a través de

>> exch=achange(57,[10 25])
exch = 
   struct with fields:
     coins: [25 10]
         c: [1 3]
      rest: 2

0 votos

¡Muchas gracias! Este código es muy bonito. Como novato supongo que no lo habría descubierto. Probablemente, me tomará algún tiempo para entender el código completamente. Así que de nuevo, ¡muchas gracias por tu ayuda!

0 votos

@Hokkaido21 He proporcionado una modificación del código para optimizar el procedimiento de asignación de las monedas. Espero que esto ayude.

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X