代码之家  ›  专栏  ›  技术社区  › 

乘以逆数是好是坏?

  •  11
  •  · 技术社区  · 5 年前

    处理时 double 数据类型是用反比乘的,是好是坏?

    哪条路是 更快 ? 哪种方式使用更少的内存? 首选哪种方式?

    MSIL如何处理这个问题?

    SquareInches = MMSquared / 645.16 
    SquareInches = MMSquared * 0.0015500031000062000124000248000496
    

    NB: 10K用户会注意到这是 this question , 因为原来的 提问者决定严责 的“评论”部分中的所有人 这个问题。

    这个问题被重新提出是因为它是一个“好”的问题。

    请“取消选中”社区wiki作为您的答案,因为我只是将其作为cw发布,这样它就不会被视为“声誉”抢占。

    相关问题:

    Should I use multiplication or division?

    11 回复  |  直到 13 年前
        1
  •  17
  •   mmcdole    15 年前

    乘反比更快。编译器不会自动优化这一点,因为这会导致精度的微小损失。(这实际上出现在D新闻组Walter Bright Frequents上,他明确表示编译器不会自动执行此操作。)通常应该进行拆分,因为这样更可读、更准确。

    如果在循环中执行一段浮点代码十亿次 你不在乎精度的微小损失 你将被同一个数除几次,然后乘以逆数可以是一个很好的优化。实际上,在一些情况下,我已经得到了显著的现实世界加速,比如用倒数相乘所描述的情况,但是这些是执行了几十亿次循环的极端边缘情况,除了乘浮点数几乎什么都不做。

        2
  •  11
  •       15 年前

    哪一个是“ 更快 “确实是一个特定于CPU的问题,或者至少CPU的特定速度快多少,是的,除法通常被认为比乘法慢。当然,所有的性能问题都可以用“它取决于”。

    但是,如果你问的是 更好的 “答案越清晰,可读性越好,而不是哪个更快。您所看到的性能改进可能是几个时钟周期的顺序,所以除非您要说做数百万次,否则您将试图节省您自己的微秒。和 没有值得牺牲可读性和可维护性的微秒优化 .

        3
  •  11
  •   Henk Holterman    15 年前

    根据编译器和硬件的不同,其好处非常小或为零。

    但它仍然很重要(在一个紧密的循环中),然后为了可读性,您应该编写

    SquareInches = MMSquared * (1 / 645.16)
    

    最好使用常数645.16。

        4
  •  5
  •   John Feminella    15 年前

    答案将取决于执行环境的体系结构。一般来说,在大多数处理器上,除法通常比乘法稍微贵一些。

    所以 除非这实际上是一个性能问题,否则我可能不会担心它。 选择更容易理解的换算系数。

        5
  •  4
  •       15 年前

    从我的VB代码计时器

    Dim SquareInches As Double
    Dim MMSquared As Double = 81
    Const d As Double = 645.16
    Const m As Double = 1 / 645.16
    Private Function TestCase1() As Boolean 'One
        'Test One Code Here
        SquareInches = MMSquared / d
        'end test code
        Return True
    End Function
    Private Function TestCase2() As Boolean 'Two
        'Test Two Code Here
        SquareInches = MMSquared * m
        'end test code
        Return True
    End Function
    

    结果

         3/17/2009 2:13:27 PM   CPU - 1.794GHz
     One - Using Division
     Two - Using Multiplication
     Outer Loops(OL)=7  Inner Loops=262,144
      ( times in ticks.  1 ms. = 10,000 ticks )
     >> Two faster, 0.0488 ticks/loop
      Ticks / Loop
     0.0342         0.0819          0.0331          0.0488
     OL Base        One             Two              One - Two
     1   8,936          21,459          8,609           12,850
     2   9,008          21,416          8,682           12,734
     3   8,965          21,423          8,643           12,780
     4   8,964          21,457          8,659           12,798
     5   8,966          21,469          8,640           12,829
     6   8,987          21,660          8,688           12,972
     7   8,963          21,429          8,802           12,627
    
      Average
     8,969          21,473          8,674           12,799
      Variance
     431.4          6,160.3         3,315.9       
      Standard Deviation
     20.8           78.5            57.6          
     3/17/2009 2:13:27 PM
    
        6
  •  3
  •   Wadih M.    15 年前

    划分算法是 更慢的 在大多数情况下都比乘法算法好。

    这是一种权衡,你可以选择更可读的方式,也可以选择更快的方式。

    // Using division operation
    SquareInches = MMSquared / 645.16 
    

    这易于读取和维护,但执行速度慢于其乘法对应项:

    // Using a multiplication 
    SquareInches = MMSquared * 0.0015500031000062000124000248000496
    

    如果您这样做,您将需要在内存中有更多的空间来存储倒数位数,但是算法的运行速度明显更快。一位用户在VS2005项目中对其进行了测试,并报告乘法版本的性能提高了8倍。

    原因是乘法可以在处理器上盲目地转换为移位和加法操作,这是CPU上最优化的操作。一个好的有符号乘法算法是布斯的算法(处理器为您做这个)。另一方面,在执行分割算法时,需要更多的控制开销,从而使分割算法的速度变慢。

    如果您需要性能,请使用加法、减法(只不过是添加两个补数)、乘法、移位,但不要使用除法。你会得到一个 大量的 如果你提前计算出所有的逆数,并用它们在除法密集型程序中进行乘法运算,这是不可忽略的改进。

        7
  •  1
  •       15 年前

    对于执行mult优化的编译器,他们可以对此进行优化(gcc做到了): 平方=平方毫米*(1/645.16)。

        8
  •  0
  •       15 年前

    如果你用一个像 645.16 然后很可能没有区别,因为编译器可以很容易地确定哪个版本更快并使用它。
    如果你除以或乘以一个变量,那么乘法可能稍微快一点,因为逻辑通常更简单。
    当然,和任何事情一样,使用分析器。

        9
  •  0
  •       15 年前

    乘法和加法是处理器支持的最快的操作。有些处理器甚至没有除法、平方根等硬件实现。

        10
  •  0
  •       15 年前

    在大多数处理器中,乘法比除法快。但对于大多数应用程序来说,这确实是微不足道的,在我看来,您最好选择可读性更好的应用程序,除非分析显示这是一条关键路径。

    如果它是一种解释性语言,那么读取源代码并将其转换为数字所需的时间将压倒实际进行数学运算所需的时间,特别是当您使用这么多有效数字进行乘法运算时。(你确定你真的需要这么多有效数字吗?)

        11
  •  0
  •   Stefan Kendall    13 年前

    我认为第一种方法显然是首选的,因为它是明确的。想象一下在别人的代码中找到这个。你怎么确定0.00155…真的是1/645.16吗?如果最初的程序员犯了错误怎么办?此外,我如何知道645.16是正确的换算系数?为了简单起见,最好不要将数字压缩或统一表示。最基本的例子如下:

    //hours per day * days per year
    int hoursPerYear = 24*365;
    

    我们可以清楚地看到这个数字是正确的,但是你怎么知道8760是正确的答案呢?如果需要执行其中许多操作,则可能需要在输入密集计算之前将数据预处理到正确的表单。这样,你就不需要难以置信的效率,问题就变得没有意义了。