绘制日志(n 超过 k)
Plot log(n over k)
我以前从未使用过Matlab,我真的不知道如何修改代码。我需要绘制 log(1000 over k),其中 k 从 1 到 1000。
y = @(x) log(nchoosek(1000,x));
fplot(y,[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)
代码有几个问题:
nchoosek
不对第二个输入进行向量化,即不接受数组作为输入。 fplot
对向量化函数工作得更快。否则可以使用,但会发出警告。
- 对于如此大的第一个输入值,
nchoosek
的结果接近溢出。例如,nchoosek(1000,500)
给出2.702882409454366e+299
,并发出警告。
nchoosek
需要整数输入。 fplot
通常使用指定限制内的 non-integer 值,因此 nchoosek
会发出错误。
您可以利用阶乘与 gamma function and the fact that Matlab has gammaln
之间的关系解决这三个问题,它直接计算伽马函数的对数:
n = 1000;
y = @(x) gammaln(n+1)-gammaln(x+1)-gammaln(n-x+1);
fplot(y,[1 1000]);
请注意,对于指定范围内的所有 x,您会得到一个带有 y 值的图,但实际上二项式系数仅定义对于 non-negative 个整数。
此解决方案使用 arrayfun
to deal with the fact that nchoosek(n,k)
要求 k
为标量。这种方法 不需要工具箱 。
此外,这使用 plot
instead of fplot
since 已经解决了如何使用 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)
请注意,对于某些大于或等于 500 的 k
值,您将收到警告
Warning: Result may not be exact. Coefficient is greater than 9.007199e+15 and is only accurate to 15 digits
因为nchoosek(1000,500) = 2.7029e+299
。正如 @Luis Mendo, this is due to realmax = 1.7977e+308
which is the largest real floating-point supported. See here 所指出的以获取更多信息。
好吧,既然你的家庭作业现在已经被剧透了,我会post一个我认为更容易理解的答案。
multiplicative formula for the binomial coefficient 表示
n over k = producti=1 to k( (n+1-i)/i )
(抱歉,无法在 SO 上编写正确的公式,如果不清楚,请参阅维基百科 link)。
要计算产品的对数,我们可以计算对数的总和:
log(product(xi)) = sum(log(xi))
因此,我们可以为所有 i
计算 (n+1-i)/i
的值,取对数,然后将前 k
个值求和以获得给定 k
.
此代码使用 cumsum
累积和来完成此操作。它在数组元素 k
的输出是从 1 到 k
.
的所有输入数组元素的总和
n = 1000;
i = 1:1000;
f = (n+1-i)./i;
f = cumsum(log(f));
plot(i,f)
另请注意 ./
,element-wise 划分。 /
在 MATLAB 中执行矩阵除法,这里不是您需要的。
syms
函数类型完全重现你想要的
syms x
y = log(nchoosek(1000,x));
fplot(y,[1 1000]);
我以前从未使用过Matlab,我真的不知道如何修改代码。我需要绘制 log(1000 over k),其中 k 从 1 到 1000。
y = @(x) log(nchoosek(1000,x));
fplot(y,[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)
代码有几个问题:
nchoosek
不对第二个输入进行向量化,即不接受数组作为输入。fplot
对向量化函数工作得更快。否则可以使用,但会发出警告。- 对于如此大的第一个输入值,
nchoosek
的结果接近溢出。例如,nchoosek(1000,500)
给出2.702882409454366e+299
,并发出警告。 nchoosek
需要整数输入。fplot
通常使用指定限制内的 non-integer 值,因此nchoosek
会发出错误。
您可以利用阶乘与 gamma function and the fact that Matlab has gammaln
之间的关系解决这三个问题,它直接计算伽马函数的对数:
n = 1000;
y = @(x) gammaln(n+1)-gammaln(x+1)-gammaln(n-x+1);
fplot(y,[1 1000]);
请注意,对于指定范围内的所有 x,您会得到一个带有 y 值的图,但实际上二项式系数仅定义对于 non-negative 个整数。
此解决方案使用 arrayfun
to deal with the fact that nchoosek(n,k)
要求 k
为标量。这种方法 不需要工具箱 。
此外,这使用 plot
instead of fplot
since 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)
请注意,对于某些大于或等于 500 的 k
值,您将收到警告
Warning: Result may not be exact. Coefficient is greater than 9.007199e+15 and is only accurate to 15 digits
因为nchoosek(1000,500) = 2.7029e+299
。正如 @Luis Mendo, this is due to realmax = 1.7977e+308
which is the largest real floating-point supported. See here 所指出的以获取更多信息。
好吧,既然你的家庭作业现在已经被剧透了,我会post一个我认为更容易理解的答案。
multiplicative formula for the binomial coefficient 表示
n over k = producti=1 to k( (n+1-i)/i )
(抱歉,无法在 SO 上编写正确的公式,如果不清楚,请参阅维基百科 link)。
要计算产品的对数,我们可以计算对数的总和:
log(product(xi)) = sum(log(xi))
因此,我们可以为所有 i
计算 (n+1-i)/i
的值,取对数,然后将前 k
个值求和以获得给定 k
.
此代码使用 cumsum
累积和来完成此操作。它在数组元素 k
的输出是从 1 到 k
.
n = 1000;
i = 1:1000;
f = (n+1-i)./i;
f = cumsum(log(f));
plot(i,f)
另请注意 ./
,element-wise 划分。 /
在 MATLAB 中执行矩阵除法,这里不是您需要的。
syms
函数类型完全重现你想要的
syms x
y = log(nchoosek(1000,x));
fplot(y,[1 1000]);