2015-05-02 28 views

回答

14

在斯卡拉,爲什麼餘(%)運算符返回一個負數?

對於模運算結果的符號有不同的約定; Wikipedia has a good article on it。斯卡拉像大多數但絕不是所有的編程語言一樣,都會得到股息的標誌(您的案例中的-3)。

在Scala中獲得正餘數的首選方法是什麼?

我懷疑是否有普遍認同的首選方式;如果是我,請使用Math.floorMod,它給出了除數的符號(示例中的2)而不是分紅的結果(這不僅僅意味着與具有不同符號的%相同的值,請參閱鏈接的JavaDoc瞭解詳情)。或者只是一個if之後(if (result < 0) { result += M; } [其中M是除數,2在您的示例中])。

+5

這不是正確的公式!例如,5不等於-12模7,2是!它應該是'if(result <0)result + = M',其中'M'是模數的基數。 –

+0

@RexKerr:歡迎編輯。 :-)我不得不承認我不是一個大數學傢伙。我已經將它複製到上面,但是也許可以進一步編輯以解釋OP的具體示例中「模數的基礎」是什麼;我見過的描述是關於除數和分紅的說法,而不是基數,我假設你並不是指數字基數......我認爲你的意思是除數,查看「floorMod」的文檔,這就是編輯我做了。 –

2

使用math.abs(-x % y)通常不會產生相同的行爲恢復了積極的模量:

scala> math.abs(-7 % 3) 
res46: Int = 1 

但是,這並不是什麼蟒蛇(返回正模量的語言)說:

In [14]: -7 % 3 
Out[14]: 2 

如果我們看看從-7增量3:

-7, -4, -1, 2, .. 

scala停止在-1,而python停止在2

9

正確的方式來獲得正模除數添加到負模量:

(-18 % 5) + 5 

取絕對值會給你在這種情況下,錯誤的解決方案,但它會如果除數工作恰好是2

如果你不知道被除數的符號,你可以做這樣的事情:

((dividend % divisor) + divisor) % divisor 
+0

small nit:'r = dividend%divisor;如果(r <0)r +除數else r'比採取另一個效率更有效 – yonil

+0

@yonil:呃......我很懷疑。雖然模運算符不如(例如)加法的效率,但我發現很難相信它比條件分支慢很多。無論如何,你的編譯器應該足夠聰明,可以根據需要將任一版本轉換成另一個版本。 – Kevin

+0

那裏沒有分支。它被編譯成執行按位操作的CPU指令。 – yonil

-2

例如,如果你想從陣列中濾除所有奇數元素,忽略負或正,則可以這樣做:

arr.filter {X => Math.abs(X%2)== 1}

1

我想添加一些現有的答案。我得到積極的其餘首選方法是一種新的方法添加到int類型如下:

object Extensions 
{ 
    implicit class ExtendedInt (val i: Int) extends AnyVal { 
     def positiveMod (m: Int) = {val x = i % m; if (x < 0) x + m else x} 
    } 
} 

在文件中要使用的方法,導入隱類:

import Extensions._ 

現在你可以做:

(-3).positiveMod(2) 

你也可以把隱含的類在包中的對象,所以你不需要調用來自同一個包的功能時導入。