日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

取模和求余运算

發布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 取模和求余运算 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 背景
  • 探究
  • 總結

被除數 dividend 用 a 表示;
除數 divisor 用 b 表示;
商 quotient 用 q 表示;
余 remainder 用 rem 表示;
模 modulo 用 mod 表示。

背景

最近在一道 Java 習題中,看到這樣的一道題:

What is the output when this statement executed: System.out.printf(-7 % 3);

正整數的取余運算大家都很熟悉,但是對于負數、實數的取余運算,確實給人很新鮮的感覺。于是我對此進行了一些探索。我發現,這里面還是頗有一點可以探索的東西的。

探究

首先,看看自然數的取模運算(定義1):

如果 a 和 b 是兩個自然數,b 非零,可以證明存在兩個整數 q 和 r,滿足 a = q*b + r 且0 ≤ r < b。其中,q 被稱為商,r 被稱為余數。

我們計算下 (-7) % 3,這個表達式正常情況下是求余數,計算過程如下圖所示:

按自然數的除法運算規則,得到商值:-3,余數:2,且完全滿足上述兩個關系表達式:-7 = (-3)*3 + 2 且 0 ≤ 2 < 3。

那么,各種編程語言和計算器是否是按照這樣的規則計算呢?下面列舉了幾個程序運算的結果:

程序語句輸出
C++(G++ 編譯)cout << (-7) % 3;-1
Java(1.6)System.out.println((-7) % 3);-1
Python 2.6(-7) % 32
百度計算器(-7) mod 32
Google 計算器(-7) mod 32

可以看到,結果特別有意思。這個問題是百家爭鳴的。看來我們不能直接把自然數的法則用在負數上。實際上,在整數范圍內,自然數的求余法則并不被很多人所接受,大家大多認可的是下面的這個(定義 2):

如果 a 和 b 是兩個自然數,b 非零,可以證明存在兩個整數 q 和 r,滿足 a = q*b + r 且0 ≤ |r| < |b|。其中,q 被稱為商,r 被稱為余數。

可以看到,上述定義導致了有負數的求余并不是我們想象的那么簡單,根據上述的定義,我們計算下 (-7) % 3,計算過程如下圖所示:


注:按自然數的除法運算規則(定義 1),商和除數的乘積要小于等于被減數才行,但是很多程序并沒有遵循定義 1的運算規則,所以依據定義 2的規則,商和除數的乘積可以大于被減數,使用上圖所示的技巧計算時,商與除數的乘積必須接近被減數,然后計算得到結果,再驗證定義 2的兩個表達式是否成立。當然了如果你直接使用定義 2的兩個表達式硬套出 p 和 r 的值也可以,不過不推薦。

如上圖所示可以得到兩組結果:

  • 商 -3,余 2
  • 商 -2,余 -1
  • 這兩組結果都滿足“定義 2”的表達式,也就是說 2 和 -1 都是 (-7) % 3 正確的結果, 所以問題來了到底余數是 2 還是 -1 呢?這個問題最后會給出答案。

    我們把 2 和 -1 分別叫做正余數和負余數。通常,整數 a 除以整數 b 時,如果得到正余數為 r1,負余數為 r2,那么存在這樣的關系:r1 = r2 + b。

    看完了 (-7) % 3,下面我們來看一看 7 % (-3) 的情況。根據定義 2,計算過程如下圖所示:

    如上圖所示,可以得到兩組結果:

  • 商 -2,余 1
  • 商 -3,余 -2
  • 語言語句輸出
    C++(G++ 編譯)cout << 7 % (-3);1
    Java(1.6)System.out.println(7 % (-3));1
    Python 2.67 % (-3)-2
    百度計算器7 mod (-3)-2
    Google 計算器7 mod (-3)-2

    從中我們看到幾個很有意思的現象:

  • Java 緊隨 C++ 的步伐,而 Python、Google、百度步調一致。難道真是物以類聚?聯想一下,Google 一直支持 Python,Python 也頗有 Web 特色的感覺,而且 Google Application Engine 也用的 Python,國內的搜索引擎也不約而同地按照 Google 的定義進行運算。

  • 可以推斷,C++ 和 Java 通常會盡量讓商更大一些。比如在 (-7) mod 3中,他們以 -2 為商,余數為 -1。在 Python 和 Google 計算器中,盡量讓商更小,所以以 -3 為商。在 7 mod (-3) 中效果相同:C++ 選擇了 3 作為商,Python 選擇了 2 作為商。但是在正整數運算中,所有語言和計算器都遵循了盡量讓商小的原則,因此 7 mod 3 結果為 1 不存在爭議,不會有人說它的余數是 -2。

  • 上述的認知其實是錯誤的,糾正如下:
    Java 和 C++ 的 % 是求余運算符,求余遵循讓商向 0 靠近的原則(即商向 0 方向舍入取整),也就是說求余是取 q 更趨近 0 時的 r,所以 Java 和 C++ 計算 7 % (-3) 的結果是 1,因為商 -2 更靠近 0;而 Python 的 % 是取模運算符,取模遵循讓商向負無窮靠近的原則(商向無窮小方向舍入取整,向負無窮方向舍入取整),也就是說取模是取 q 更趨近無窮小(負無窮)時的 r,所以 Python、百度、谷歌輸出的結果是 -2,因為 -3 更靠近負無窮的方向。

    如果按照第二點的推斷,我測試一下 (-7) % (-3),結果應該是前一組語言(C++,Java)返回 2,后一組返回 -1。(請注意這只是假設)

    于是我做了實際測試:

    語言語句輸出
    C++(G++ 編譯)cout << -7 % (-3);-1
    Java(1.6)System.out.println(-7 % (-3));-1
    Python 2.6-7 % (-3)-1
    百度計算器-7 mod (-3)-1
    Google 計算器-7 mod (-3)-1

    結果讓人大跌眼鏡,所有語言和計算機返回結果完全一致。

    這個眼鏡也白跌了,上述結果完全符合求余時商向 0 靠近的原則,取模時商向負無窮方向靠近的原則,所以都輸出 -1 根本就在預料之內。

    我們看下 (-7) % (-3) 的運算過程,如下圖所示:

    所以根據求余時商向 0 靠近的原則,取模時商向負無窮方向靠近的原則,求余和取模的商都選擇 2,所以余數和模數都是 -1,結果輸出的都是 -1。

    總結

    我們由此可以總結出下面兩個結論:

  • 對于任何同號的兩個整數,其取余結果沒有爭議,所有語言的運算原則都是使商盡可能小。
  • 對于異號的兩個整數,C++/Java語言的原則是使商盡可能大,很多新型語言和網頁計算器的原則是使商盡可能小。
  • 這個總結也是錯誤的。

    最后總結:除法運算遵循定義 2的規則,求余是取 q 更趨近 0 時的 r,取模是取 q 更趨近負無窮的 r,如果被除數和除數符號相同,因為取相同的商值,所以余數和模數相同,被除數和除數的符號不同,則余數和模數會不同。

    總結

    以上是生活随笔為你收集整理的取模和求余运算的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。