我想用scala(递归)编写一个totient-function。
Euler的totient函数对直到给定整数n的正整数进行计数,这些整数相对于n
我想到了:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
@tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
private def isDividable(divisor: Int) = number % divisor == 0
}
}
出于可读性考虑,我创建了一个小函数isDividable
。
我想在递归helper
方法中使用此函数。
不幸的是,我收到以下错误:
Error:(12, 22) value isDividable is not a member of Int
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
问题:有人可以向我解释,我做错了什么以及如何解决?
编辑:
为完整起见,我将添加totient函数的有效实现:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
@tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 0) accumulator
else {
if (number.isCoprimeTo(currentN)) helper(currentN - 1, accumulator + 1)
else helper(currentN - 1, accumulator)
}
helper(number, 0)
}
private[Totient] def isCoprimeTo(otherNumber: Int): Boolean = {
gcd(number, otherNumber) == 1
}
private def gcd(firstNumber: Int, secondNumber: Int): Int =
if (secondNumber == 0) firstNumber else gcd(secondNumber, firstNumber % secondNumber)
}
}
答案 0 :(得分:4)
private
没有额外的信息意味着“只有通过其他改进方法才能访问,但是对于相同的改进实例”。
这意味着您可以调用isDividable
来获得与调用totient / helper相同的number
的结果,但是它不会成为扩展方法(因为在外部看不到)改进)。
为解决此问题,您可以更改方法的范围,例如使它对Totient
中定义的所有方法可见:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
@tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
// notice [Totient] after private
private[Totient] def isDividable(divisor: Int) = number % divisor == 0
}
}
这会在我的炸药中编译并起作用:
@ import Totient._
import Totient._
@ 12.totient
res2: Int = 6
答案 1 :(得分:0)
另一种选择是从isDividable
而不是isCoprimeTo
调用this
/ number
。这样,编译器根本不必执行隐式解析即可获取该方法。使用您的原始代码:
def totient: Int = {
@tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (this.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
(您甚至可以完全忽略对this
的调用,而只需拥有isDividable(currentN)
,但这会使代码不太清晰。)