提问人:Corey Ogburn 提问时间:11/15/2019 更新时间:9/2/2022 访问量:160
!= 0 与 > 0 检查数组是否为空时?
!= 0 vs > 0 when checking if an array is empty or not?
问:
在过去的几年里,我已经争论过十几次写这个问题。主要是因为我不确定这是否重要。我正在寻找最技术性的答案,因为从表面上看,我知道这并不重要。
您通常的编程语言为您提供了一些方法来使用数组上的字段(即 C#)或传递数组的函数(即 Go)来确定数组/列表/集合的大小,并且通常使用这些方法之一来检查数组是否为空或其中是否有任何值。你并不在乎有多少,只关心列表是否为空。arr.Length
len(arr)
在检查数组是否为空时,我在以下两者之间来回切换:
if (arr.Length != 0) { /* do something with the array */ }
和
if (arr.Length > 0) { /* do something with the array */ }
毫无疑问,两个运营商都完成了这项工作。由于数组的长度不能为负数(至少在我所知道的任何语言中都没有),因此它们的行为不可能有所不同。两者都没有明显的开销。
如果(一个很大的假设)这两者之间有任何区别,我想它会在一两个时钟周期的量级上,但我对低级事件的了解还不够,没有任何理由偏袒一个而不是另一个。
出于好奇,在任何流行语言中,它们之间有丝毫区别吗?运行时速度有区别吗?编译时?二进制大小?从字面上看,除了输出二进制文件中的不同操作码之外,还有什么吗?解释型语言与编译型语言会有所不同吗?
答:
据我所知,两者之间没有区别。逻辑运算符的计算取决于正在检查的内容,而不是运算符的类型。咬合大小会随着写入两个字符而不是一个字符而变化,但我不确定编译时间。每天编写代码由您决定使用哪个,我个人更喜欢它,因为它看起来更清晰!=
免責聲明:这与其说是回答,不如说是评论
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>
第一个是最慢的。最后一个是最快的。
评论
tick
毫无疑问,如果其中任何一个性能更高,它应该是:
if (arr.Length != 0) { /* do something with the array */ }
空指针检查在 C 中经常发生,硬件制造商将尽可能地优化指令。jnz
这真的重要吗?不,编译器可能会在首选时使两者等效,并且无论如何差异通常可以忽略不计。
但是,也更清楚。使用或通常暗示您期望一些其他值。!=
>
<
在某些语言中,它也可能是更容易的选择。例如,在 PHP 中检查字符串是否不为空:
if (strlen(string))
该条件实质上是检查:
if (strlen(string) != 0)
this->size() == 0
是什么 GCC 选择value.length == 0
是 Java 选择的
鉴于这种微优化可能根本不算数(除非你用基准证明相反),最好偏爱表现力。
许多语言/库/类提供或检查。
如果你使用这样的语言,你最终也可以写empty
isEmpty
if ( not(isempty(array)) ) ...
if ( not( array.empty() ) ) ...
array isEmpty ifFalse: [ ... ]
例如,Pharo Smalltalk 有一个 lint 规则,用于阻止模式并替换为 ...array size = 0
array isEmpty
编辑
此外,在动态类型语言的上下文中,将算法限制在数组容器中,就代码演变、可扩展性和健壮性而言,这不一定是一个好主意。
如果只是优化问题,对于其他类型的集合/容器来说,获取长度(大小)可能并不便宜。
例如,获取 LinkedList 的长度可能会花费 O(N) 中的遍历。
相反,空度测试在O(1)中很容易实现。
无论我收到多少反对票,我都会重申我的建议,即使用更高层次的结构。
下一个:子句包含算法
评论