【问题标题】:!= 0 vs > 0 when checking if an array is empty or not?!= 0 vs > 0 检查数组是否为空?
【发布时间】:2020-03-11 00:49:10
【问题描述】:

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

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

在检查数组是否为空时,我在以下之间来回徘徊:

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

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

毫无疑问,两位操作员都能胜任。因为你不能有一个负长度的数组(至少不是我所知道的任何语言),所以他们没有办法表现得不同。两者都没有明显的开销。

如果(一个很大的如果)这两者之间有任何区别,我想它会在一个或两个时钟周期的数量级上,但我对低级事件的了解不够,没有任何理由支持一个胜过其他。

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

【问题讨论】:

    标签: arrays optimization language-agnostic


    【解决方案1】:

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

    【讨论】:

      【解决方案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>
      

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

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

      【讨论】:

      • 我并不感到惊讶,“没有比较,整数也可以是布尔值”方法更快,我只是没有提到我的问题,因为并非所有语言都支持它。 ColdFusion 中的tick 到底是什么?一毫秒?一纳秒?它是一个合适的计时器还是只是用来告诉时间?抱歉,我不熟悉 ColdFusion。
      • 刻度是毫秒。
      【解决方案3】:

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

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

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

      这真的很重要吗?不,当首选一个时,编译器可能会使两者等价,而且差异通常可以忽略不计。

      不过,!= 也更清晰。使用 &gt;&lt; 通常暗示您期望一些其他值。

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

      if (strlen(string))
      

      那个条件本质上是检查:

      if (strlen(string) != 0)
      

      • this-&gt;size() == 0what GCC chose
      • value.length == 0 是 Java 选择的

      【讨论】:

        【解决方案4】:

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

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

        if ( not(isempty(array)) ) ...
        
        if ( not( array.empty() ) ) ...
        
        array isEmpty ifFalse: [ ... ]
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-02-25
          • 2022-01-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多