!= 0 与 > 0 检查数组是否为空时?

!= 0 vs > 0 when checking if an array is empty or not?

提问人:Corey Ogburn 提问时间:11/15/2019 更新时间:9/2/2022 访问量:160

问:

在过去的几年里,我已经争论过十几次写这个问题。主要是因为我不确定这是否重要。我正在寻找最技术性的答案,因为从表面上看,我知道这并不重要。

您通常的编程语言为您提供了一些方法来使用数组上的字段(即 C#)或传递数组的函数(即 Go)来确定数组/列表/集合的大小,并且通常使用这些方法之一来检查数组是否为空或其中是否有任何值。你并不在乎有多少,只关心列表是否为空。arr.Lengthlen(arr)

在检查数组是否为空时,我在以下两者之间来回切换:

if (arr.Length != 0) { /* do something with the array */ }

if (arr.Length > 0) { /* do something with the array */ }

毫无疑问,两个运营商都完成了这项工作。由于数组的长度不能为负数(至少在我所知道的任何语言中都没有),因此它们的行为不可能有所不同。两者都没有明显的开销。

如果(一个很大的假设)这两者之间有任何区别,我想它会在一两个时钟周期的量级上,但我对低级事件的了解还不够,没有任何理由偏袒一个而不是另一个。

出于好奇,在任何流行语言中,它们之间有丝毫区别吗?运行时速度有区别吗?编译时?二进制大小?从字面上看,除了输出二进制文件中的不同操作码之外,还有什么吗?解释型语言与编译型语言会有所不同吗?

数组 优化 与语言无关

评论


答:

0赞 Alessandro Gregolin 11/15/2019 #1

据我所知,两者之间没有区别。逻辑运算符的计算取决于正在检查的内容,而不是运算符的类型。咬合大小会随着写入两个字符而不是一个字符而变化,但我不确定编译时间。每天编写代码由您决定使用哪个,我个人更喜欢它,因为它看起来更清晰!=

0赞 James A Mohler 11/15/2019 #2

免責聲明:这与其说是回答,不如说是评论

ColdFusion 在 JVM 上运行,我在 ColdFusion 中运行了它

<cfscript>
    final iterations = 100000;

    final arr = [];

    starttick = getTickCount();
    for (x = 1; x < iterations; x++)  {
        if(arr.len() != 0)    {
            //
        }
    }
    writeoutput("<br />");
    writeoutput(getTickCount() - starttick);

    starttick = getTickCount();
    for (x = 1; x < iterations; x++)  {
        if(arr.len() > 0)    {
            //
        }
    }
    writeoutput("<br />");
    writeoutput(getTickCount() - starttick);

    starttick = getTickCount();
    for (x = 1; x < iterations; x++)  {
        if(arr.len())    {
            //
        }
    }
    writeoutput("<br />");
    writeoutput(getTickCount() - starttick);

</cfscript>

<p>Done</p>

第一个是最慢的。最后一个是最快的。

enter image description here

请参见:https://cffiddle.org/app/file?filepath=2b69483a-0244-46ff-a635-7ec1d0781ab1/78475e78-0d39-404b-85cc-877ee52ae9a7/c0dce98e-170e-4130-b78b-912e3c41d16d.cfm

评论

0赞 Corey Ogburn 11/19/2019
我对“没有比较,ints 也可以是布尔值”方法更快并不感到惊讶,我只是没有提到我的问题,因为并非所有语言都支持它。ColdFusion 中的 a 到底是什么?一毫秒?纳秒?它是合适的天文台表还是只是用来报时的?对不起,我不熟悉 ColdFusion。tick
0赞 James A Mohler 11/19/2019
滴答是毫秒。
0赞 Anonymous 11/15/2019 #3

毫无疑问,如果其中任何一个性能更高,它应该是:

if (arr.Length != 0) { /* do something with the array */ }

空指针检查在 C 中经常发生,硬件制造商将尽可能地优化指令。jnz

这真的重要吗?不,编译器可能会在首选时使两者等效,并且无论如何差异通常可以忽略不计。

但是,也更清楚。使用或通常暗示您期望一些其他值。!=><

在某些语言中,它也可能是更容易的选择。例如,在 PHP 中检查字符串是否不为空:

if (strlen(string))

该条件实质上是检查:

if (strlen(string) != 0)

0赞 aka.nice 11/16/2019 #4

鉴于这种微优化可能根本不算数(除非你用基准证明相反),最好偏爱表现力。

许多语言/库/类提供或检查。
如果你使用这样的语言,你最终也可以写
emptyisEmpty

if ( not(isempty(array)) ) ...

if ( not( array.empty() ) ) ...

array isEmpty ifFalse: [ ... ]

例如,Pharo Smalltalk 有一个 lint 规则,用于阻止模式并替换为 ...array size = 0array isEmpty

编辑

此外,在动态类型语言的上下文中,将算法限制在数组容器中,就代码演变、可扩展性和健壮性而言,这不一定是一个好主意。
如果只是优化问题,对于其他类型的集合/容器来说,获取长度(大小)可能并不便宜。
例如,获取 LinkedList 的长度可能会花费 O(N) 中的遍历。
相反,空度测试在O(1)中很容易实现。

无论我收到多少反对票,我都会重申我的建议,即使用更高层次的结构。