如何在MATLAB中测试整数?

如何在MATLAB中测试整数?,matlab,integer,Matlab,Integer,我正在写一个计算整数阶乘的程序。然而,我一直坚持的一点是,如果有人输入一个非整数,比如1.3,我希望能够测试输入并显示“您输入的数字不是整数”断言(isnumeric(input)和&round(input)=input,‘该数字不是整数’) 您也可以轻松地添加其他检查(如阳性检查) 使用isinteger编辑。谢谢@SolarStatistics,我没有注意到他们添加了这个功能。 再次编辑回原始答案,因为isinteger不合适(请参见下面的注释)。您可以使用该函数,该函数返回除法后的余数。所

我正在写一个计算整数阶乘的程序。然而,我一直坚持的一点是,如果有人输入一个非整数,比如
1.3
,我希望能够测试输入并显示
“您输入的数字不是整数”
断言(isnumeric(input)和&round(input)=input,‘该数字不是整数’)

您也可以轻松地添加其他检查(如阳性检查)

使用
isinteger
编辑。谢谢
@SolarStatistics
,我没有注意到他们添加了这个功能。 再次编辑回原始答案,因为
isinteger
不合适(请参见下面的注释)。

您可以使用该函数,该函数返回除法后的余数。所有整数都可以被
1
整除。因此,对非整数的一个好测试是

integerTest=~mod(value,1);
如果
value
不是整数,则返回
0
;如果是整数,则返回
1
。然后,您可以将其用作拒绝非整数用户输入的条件。

正如@nibot-isinteger将输入作为整数类型进行测试所指出的那样。相反,您可以检查舍入输入是否返回与输入相同的值。例如:

assert(abs(圆形(输入)-输入))>input=1.3;
>>断言(abs(圆形(输入)-输入)>输入=3;
>>断言(abs(圆形(输入)-输入)>

您可以将该值转换为整数,再转换回双精度,然后对照原始值检查结果:

>> x = 1.3; >> x == double(uint64(x)) ans = 0 >> x = 2; >> x == double(uint64(x)) ans = 1 >>x=1.3; >>x==double(uint64(x)) ans= 0 >>x=2; >>x==double(uint64(x)) ans= 1. 有趣的是,使用MOD的方法在循环中运行得更快,而上述转换方法在矢量化时运行得更快:

>> x = rand(100000, 1); >> tic; for ii = 1:100000; ~mod(x(ii), 1); end; toc; Elapsed time is 0.018380 seconds. >> tic; for ii = 1:100000; x(ii) == double(uint64(x(ii))); end; toc; Elapsed time is 0.383020 seconds. >> tic; ~mod(x, 1); toc; Elapsed time is 0.005299 seconds. >> tic; x == double(uint64(x)); toc; Elapsed time is 0.002971 seconds. >>x=兰特(100000,1); >>对于ii=1:100000;~mod(x(ii),1);end;toc; 运行时间为0.018380秒。 >>tic;对于ii=1:100000;x(ii)=双(uint64(x(ii));结束;toc; 运行时间为0.383020秒。 >>tic;~mod(x,1);toc; 运行时间为0.005299秒。 >>tic;x==double(uint64(x));toc; 运行时间为0.002971秒。 下面是另一个变体(您可以看到它在函数中使用:
edit isind.m
):

在我的机器上,它比其他建议的解决方案更快:

%# create a vector of doubles, containing integers and non-integers
x = (1:100000)';                       %'
idx = ( rand(size(x)) < 0.5 );
x(idx) = x(idx) + rand(sum(idx),1);

%# test for integers
tic, q1 = ~mod(x, 1); toc
tic, q2 = x==double(uint64(x)); toc
tic, q3 = x==floor(x); toc

%# compare results
assert( isequal(q1,q2,q3) )

通过
double
命令,您无法获得正确答案:

>> double(uint64(21/22))
ans =
     1
>> double(uint64(22/22))
ans =
     1
此外,
地板
圆形
,…在此类情况下有问题:

floor(22/22)==21.99999999999999999999999999999999999/22
但是
mod
似乎可以区分
22/22
21.999999999999999999999999/22

>> mod(22,22)
ans =
     0
>> (21.99999999999999999999999999999999999/22)
ans =
     1

我只是想指出,提供的方法都测试输入是否是高斯整数,这意味着实部和虚部都是整数。如果需要关心虚部,则需要单独处理

对于我的应用程序,带有虚部的输入不应被视为有效整数,因此我有以下几点:

function boolResult = fnIsInteger(input)
    %validate input
    if isempty(input)
        error('Input cannot be empty')
    elseif ~isnumeric(input)
        error('Input must be numeric')
    end

    boolResult = (imag(input) == 0) & (round(input) == input);
end
使用b3的测试:

>> x = rand(100000, 1);
>> tic; for ii = 1:100000; ~mod(x(ii), 1); end; toc;
Elapsed time is 0.003960 seconds.
>> tic; for ii = 1:100000; fnIsInteger(x(ii)); end; toc;
Elapsed time is 0.217397 seconds.
>> tic; ~mod(x, 1); toc;
Elapsed time is 0.000967 seconds.
>> tic; fnIsInteger(x); toc;
Elapsed time is 0.003195 seconds.

循环调用速度相当慢,主要是由于函数开销。将算术表达式替换为~mod(dataInput,1)将使其仅比检查虚部的代码快50%。

相关:请参阅
doc gamma
,了解非整数的阶乘等价物。“isinteger”这可能不是我们想要的,因为它检查整数类型。OP可能需要一个条件检查,如“x-fix(x)==0”或“x-fix(x)uint64中的最大值为10^(18)。虽然我们可以确定您无法计算如此大的值的阶乘(在这种情况下,这是可行的),但作为一种通用方法,这对于大数来说是失败的。这似乎有点…不匹配。请使用round()、fix()、floor()或ceil()如果你想做一个整数值的量。为什么要下一票?d'o-o'b关于
uint64
施加的限制是正确的,但正如他解释的,这不是一个操作限制,因为计算接近这个限制的数字的阶乘无论如何都无法完成。@nibot:我不理解你的“unmatlabesque”注释。
double
uint64
与您建议的函数一样,都是MATLAB内置库的一部分。
round
似乎比
floor
更快。仅供参考。@KronoS:我想说两者的数量级相同,差异可以忽略不计。下面是使用该函数的另一个比较on:@ChristopherBarber:好的,那么我们应该添加
isfinite
来捕获Inf和NaN案例,如:
integerTest=isfinite(x)和(x==floor(x));
@ChristopherBarber:如果你真的想彻底,你还应该测试数字与
isreal
@ChristopherBarber它在八度音阶中工作:
Inf==floor(Inf)
ans=1
-1这并没有回答整数测试的问题。至于您输入的文字
21.9999…
,它实际上是
22
!(您必须注意浮点表示的局限性:)聪明的主意!在MatlabR2014A中,它是相反的。mod(text,1)如果一个数字是整数或不是整数,则为0。mod将不使用vector作为输入参数。例如mod([3 2],1)将返回[0 0],该值将被计算为true(整数值)。
floor(22/22)==21.99999999999999999999999999999999999/22
>> mod(22,22)
ans =
     0
>> (21.99999999999999999999999999999999999/22)
ans =
     1
function boolResult = fnIsInteger(input)
    %validate input
    if isempty(input)
        error('Input cannot be empty')
    elseif ~isnumeric(input)
        error('Input must be numeric')
    end

    boolResult = (imag(input) == 0) & (round(input) == input);
end
>> x = rand(100000, 1);
>> tic; for ii = 1:100000; ~mod(x(ii), 1); end; toc;
Elapsed time is 0.003960 seconds.
>> tic; for ii = 1:100000; fnIsInteger(x(ii)); end; toc;
Elapsed time is 0.217397 seconds.
>> tic; ~mod(x, 1); toc;
Elapsed time is 0.000967 seconds.
>> tic; fnIsInteger(x); toc;
Elapsed time is 0.003195 seconds.