使用Scala'更高级的数学;s数字和小数
最近,我(终于)开始使用Scala的数字特性,这确实很神奇。例如:使用Scala'更高级的数学;s数字和小数,scala,math,exponent,Scala,Math,Exponent,最近,我(终于)开始使用Scala的数字特性,这确实很神奇。例如: def square[A](x: A)(implicit num: Numeric[A]): A = num.times(x, x) 现在我可以对任何数字进行平方运算,无论是双精度、整数、大十进制,还是其他数字。然而,如果我想做一些更高级的数学呢?例如,我的ForDouble数字如下所示: def logisticFunction(x: Double): Double = 1.0 / (1.0 + math.exp(-x))
def square[A](x: A)(implicit num: Numeric[A]): A = num.times(x, x)
现在我可以对任何数字进行平方运算,无论是双精度
、整数
、大十进制
,还是其他数字。然而,如果我想做一些更高级的数学呢?例如,我的ForDouble
数字如下所示:
def logisticFunction(x: Double): Double = 1.0 / (1.0 + math.exp(-x))
type FromDouble[A] = Double => A
type ToDouble [A] = A => Double
def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0 / (1.0 + math.exp(-x))
logisticFunction(0.5)
implicit def bigDecimalToDouble(b: BigDecimal) = b.toDouble
logisticFunction(BigDecimal(0.5))
我可以很容易地做加法和除法(我只需要使用traitfractive
而不是Numeric
),但是指数呢?我当然不想编写自己的exp
函数(或任何接受双参数的任意函数)
所以,我的问题是:如何将我的A
转换为Double
,在这方面做数学运算,然后再转换回A
。有可能吗
编辑:
这就是我的函数签名的外观:
def logisticFunction[A](x: A)(implicit num: Fractional[A]): A =
/* Magic happens here */
我已经了解了转换为double的部分,这与num.toDouble(x)
一样简单。但是,转换回A
的问题仍然存在。您需要一个提供三角函数的类型类,例如exp
。Scala的标准库并没有超出分数
。你可以尝试使用
例如:
$ sbt core/console
import spire.math._
import spire.algebra._
import spire.implicits._
def logisticFunction[A](x: A)(implicit m: Field[A], t: Trig[A]): A =
m.one / (m.one + exp(-x))
logisticFunction(0.5)
logisticFunction(BigDecimal(0.5))
我仍然怀疑这种方法是否真的有用。但根据您的描述,您将需要以下内容:
def logisticFunction(x: Double): Double = 1.0 / (1.0 + math.exp(-x))
type FromDouble[A] = Double => A
type ToDouble [A] = A => Double
def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0 / (1.0 + math.exp(-x))
logisticFunction(0.5)
implicit def bigDecimalToDouble(b: BigDecimal) = b.toDouble
logisticFunction(BigDecimal(0.5))
或使用专用类型类别:
object FromDouble {
implicit object _Double extends FromDouble[Double] {
def apply(d: Double) = d
}
implicit object _BigDecimal extends FromDouble[BigDecimal] {
def apply(d: Double) = BigDecimal(d)
}
}
trait FromDouble[A] extends (Double => A)
object ToDouble {
implicit object _Double extends ToDouble[Double] {
def apply(d: Double) = d
}
implicit object _BigDecimal extends ToDouble[BigDecimal] {
def apply(b: BigDecimal) = b.toDouble
}
}
trait ToDouble[A] extends (A => Double)
def logisticFunction[A: FromDouble: ToDouble](x: A): A = 1.0 / (1.0 + math.exp(-x))
logisticFunction(0.5)
logisticFunction(BigDecimal(0.5))
logisticFunction永远不会返回例如Integer的有效成员,因此,我看不出这是怎么可能的,除非你想开始将它作为一个部分应用的函数使用,并修改它以匹配函数的有效数字类型。导入numeric.Implicits.\u
并写入x*x
而不是num.times(x,x)
。很抱歉问这个明显的问题,但我假设这里有更复杂的应用程序在工作?考虑到这些函数有多简单,为什么要使用数值函数来编写它们?我这样说是因为,老实说,你想在日常生活中避免使用Scala的大部分花哨功能,相信我,在强健的金融系统中,许多功能,如隐式功能,是没有立足之地的。@RichardTodd我不确定“在这方面相信我”在问答网站上有多大的地位,特别是当人们不知道你是谁的时候。为你的位置提供理由有多难?Shadowlands,我会使用分数[a],而不是数字[a]作为逻辑函数。不管怎样,这个函数对整数没有任何意义。Jean-Philippe Pellet,我试过了,但是编译器给了我一些毛茸茸的错误(“错误:类型不匹配;[…]请注意,隐式转换不适用,因为它们是不明确的”)。Richard Todd,是的,这些只是最小的示例,不是我的实际代码。如果我不想使用Scala的特性,我只想使用Java:)我的问题不在于数字。我想创建一个通用方法,它接受任何分数(Double,Float,BigDecimal),对其进行运算并返回相同类型的结果。我可以用简单的运算(+,*,等等)来实现这一点,但不能用接受Double的任意函数。然后,您需要类型类来转换为Double或从Double转换为Double,尽管奇怪的是,如果使用Double
进行此运算,您首先要进行前后转换