Je n'ai jamais utilisé Matlab auparavant et je ne sais vraiment pas comment corriger le code. J'ai besoin de tracer le journal (1000 sur k) avec k allant de 1 à 1000.
Warning: Function behaves unexpectedly on array inputs. To improve performance, properly vectorize your function to return an output with the same size and shape as the input arguments. In matlab.graphics.function.FunctionLine>getFunction In matlab.graphics.function.FunctionLine/updateFunction In matlab.graphics.function.FunctionLine/set.Function_I In matlab.graphics.function.FunctionLine/set.Function In matlab.graphics.function.FunctionLine In fplot>singleFplot (line 241) In fplot>@(f)singleFplot(cax,{f},limits,extraOpts,args) (line 196) In fplot>vectorizeFplot (line 196) In fplot (line 166) In P1 (line 5)
Erreur:
y = @(x) log(nchoosek(1000,x)); fplot(y,[1 1000]);
4 Réponses :
Il y a plusieurs problèmes avec le code:
nchoosek
ne vectorise pas sur la deuxième entrée, c'est-à-dire qu'il n'accepte pas de tableau comme entrée. fplot
fonctionne plus rapidement pour les fonctions vectorisées. Sinon, il peut être utilisé, mais il émet un avertissement. nchoosek
est proche du débordement pour des valeurs aussi importantes de la première entrée. Par exemple, nchoosek (1000,500)
donne 2,702882409454366e + 299
et émet un avertissement. nchoosek
attend des entrées entières. fplot
utilise en général des valeurs non entières dans les limites spécifiées, et donc nchoosek
génère une erreur. Vous pouvez résoudre ces trois problèmes en exploitant la relation entre la factorielle et la fonction gamma et le fait que Matlab a gammaln
, qui calcule directement le logarithme de la fonction gamma:
n = 1000; y = @(x) gammaln(n+1)-gammaln(x+1)-gammaln(n-x+1); fplot(y,[1 1000]);
Notez que vous obtenez un tracé avec des valeurs y pour tous x dans la plage spécifiée, mais en réalité le coefficient binomial n'est défini que pour les entiers non négatifs.
p >
Excellente et intelligente exploitation de la fonction factorielle et gamma (+1). De plus, je n'étais pas au courant de la fonction gammaln
. Merci!
Cette solution utilise arrayfun
pour gérer le fait que nchoosek (n, k) code >
nécessite que k
soit un scalaire. Cette approche ne nécessite aucune boîte à outils .
En outre, cela utilise plot
a > au lieu de fplot
depuis cette réponse intelligente explique déjà comment faire avec fplot
.
% MATLAB R2017a n = 1000; fh=@(k) log(nchoosek(n,k)); K = 1:1000; V = arrayfun(fh,K); % calls fh on each element of K and return all results in vector V plot(K,V)
Notez que pour certaines valeurs de k
supérieures ou égales à 500, vous recevrez l'avertissement
Attention: le résultat peut ne pas être exact. Le coefficient est supérieur à 9,007199e + 15 et n'est précis qu'à 15 chiffres
car nchoosek (1000,500) = 2.7029e + 299
. Comme indiqué par @Luis Mendo , cela est dû à realmax = 1.7977e + 308 code > qui est la plus grande virgule flottante réelle prise en charge. Voir ici pour plus d'informations.
OK, puisque vous avez de toute façon reçu des spoilers pour votre exercice de devoirs, je posterai une réponse que je pense être plus facile à comprendre.
Le formule multiplicative pour le coefficient binomial dit que
n sur k = produit i = 1 à k ((n + 1-i) / i)
(désolé, pas moyen d'écrire des formules appropriées sur SO, voir le lien Wikipedia si ce n'était pas clair).
Pour calculer le logarithme d'un produit, nous pouvons calculer la somme des logarithmes:
log (produit (x i )) = somme (log (x i ))
Ainsi, nous pouvons calculer les valeurs de (n + 1-i) / i
pour tout i
, prendre le logarithme, puis résumer les premières valeurs de k
pour obtenir le résultat pour un k
donné .
Ce code accomplit qu'en utilisant cumsum
, le cumul somme. Sa sortie à l'élément de tableau k
est la somme de tous les éléments de tableau d'entrée de 1 à k
.
n = 1000; i = 1:1000; f = (n+1-i)./i; f = cumsum(log(f)); plot(i,f)
Notez également ./
, la division par élément. /
effectue une division matricielle dans MATLAB, et ce n'est pas ce dont vous avez besoin ici.
C'est intelligent. Je n'avais pas envisagé l'approche somme des logs mais rend parfait depuis maintenant que vous l'énoncez. Approche très nette et propre. (+1)
Autre support de site SE utilisant MathJax pour rendre LaTex. Cela semble également être une fonctionnalité très utile sur SO.
@John: Cette suggestion a été discutée et rejetée plusieurs fois sur Meta. Ils ne veulent pas le faire, malheureusement.
@CrisLuengo Ouais, je suis juste allé dans un terrier de lapin pour enquêter sur ça. On dirait que cela revient souvent et nous vivons juste avec une composition moche et une communication inefficace pour des raisons ...
nchoosek
a besoin d'une entrée scalaire. Vous devez utiliser une boucle pour calculer son résultat pour chaquek
séparément. Mais là encore, je pense que votre exercice est destiné à ne pas utilisernchoosek
, car les valeurs intermédiaires sont énormes et ne rentreront probablement pas dans les nombres à virgule flottante double précision (ou du moins donneront des résultats erronés) . Quelle est l'équation pour log (n sur k)?cela vous aidera tutorialspoint.com/matlab/matlab_plotting.htm
Copie possible de ajustement et tracé d'une parabole, matlab
Pas du tout un doublon. Cette question utilise
fplot
(qui prend une fonction anonyme comme entrée), tandis que l'autre utiliseplot
(qui prend des vecteurs numériques). En outre, cette question présente des problèmes potentiels de précision numérique, en raison des grands nombres impliqués dans l'approche du PO@LuisMendo Étant donné que ses données sont toutes discrètes, il serait probablement plus logique pour lui d'utiliser plot que fplot pour cette application.