gpt4 book ai didi

scala - Scala Numeric[T] 的问题

转载 作者:行者123 更新时间:2023-12-01 09:27:08 25 4
gpt4 key购买 nike

我有一个数字求解函数 (Double => Double),我试图聪明地使用 Numeric[T] 来将两种数字分开.

事实证明这并不容易。剩下的问题是:

  • 如何做除法; Numeric[T] 只有加号、减号等运算符。
  • 为什么编译器找不到隐含证据$1: Numeric[Double] 函数(参见下面的编译器输出)

理想情况下,我想说,“AB 都是 Double,但如果我将它们混合在一起,请告诉我其他”。

代码如下:

import scala.annotation.tailrec

class Sweep[A: Numeric, B: Numeric]( fDiff: A => B, initialSeed: A, initialStep: A, bEps: B )
{
val anum= evidence$1
val bnum= evidence$2

assert( anum.signum(initialStep) > 0 )
assert( bnum.lt( fDiff(initialSeed), fDiff( anum.plus(initialSeed,initialStep) )) ) // check that it's an increasing function

@tailrec
private def sweep( seed: A, step: A ): A = {
val bDiff= fDiff(seed)

if ( bnum.lt( bnum.abs(bDiff), bEps) ) { // done
seed
} else if ( bnum.signum(bDiff) != anum.signum(step) ) {
sweep( anum.plus(seed,step), step ) // continue, same step and direction ('bDiff' should go smaller)
} else {
val newStep = anum.toDouble(step) / -2.0
sweep( anum.minus(seed,newStep), newStep ) // reverse, smaller step
}
}

// Make sure we take the initial step in the right direction
//
private lazy val stepSign= -bnum.signum( fDiff(initialSeed) )

def apply: A = sweep( initialSeed, stepSign * initialStep )
}

object TestX extends App {

val t= new Sweep( (a: Double) => (a*a)-2, 1.0, 0.5, 1e-3 )()

println( t, math.sqrt(2.0) )
}

我也尝试过使用旧的 (implicit anum: Numeric[A]) 参数,但是无法有两个这样的参数(AB).

这是编译器所说的(Scala 2.9):

fsc -deprecation -d out-make -unchecked src/xxx.scala
src/xxx.scala:25: error: type mismatch;
found : newStep.type (with underlying type Double)
required: A
sweep( anum.minus(seed,newStep), newStep ) // reverse, smaller step
^
src/xxx.scala:33: error: overloaded method value * with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (A)
def apply: A = sweep( initialSeed, stepSign * initialStep )
^
src/xxx.scala:38: error: not enough arguments for constructor Sweep: (implicit evidence$1: Numeric[Double], implicit evidence$2: Numeric[Double])Sweep[Double,Double].
Unspecified value parameters evidence$1, evidence$2.
val t= new Sweep( (a: Double) => (a*a)-2, 1.0, 0.5, 1e-3 )()
^
three errors found

感谢您的任何想法。

最佳答案

您想使用 Fractional 而不是 Numeric。以下为我编译:

import scala.annotation.tailrec
import math.Fractional.Implicits._
import Ordering.Implicits._

class Sweep[A: Fractional, B: Fractional](fDiff: A => B, initialSeed: A, initialStep: A, bEps: B) {
val aFractional = implicitly[Fractional[A]]

assert(initialStep.signum > 0)
assert(fDiff(initialSeed) < fDiff(initialSeed + initialStep))

@tailrec
private def sweep(seed: A, step: A): A = {
val bDiff = fDiff(seed)
if (bDiff.abs < bEps) {
seed
} else if (bDiff.signum != step.signum) {
sweep(seed + step, step)
} else {
val one = aFractional.one
val newStep = step / aFractional.fromInt(-2)
sweep(seed - newStep, newStep)
}
}

private lazy val stepSign = aFractional.fromInt(-fDiff(initialSeed).signum)
def apply: A = sweep(initialSeed, stepSign * initialStep)
}

val sweep = new Sweep((a: Double) => (a*a)-2, 1.0, 0.5, 1e-3)
println(sweep.apply, math.sqrt(2.0))

请注意,要在 A 类型中获取类似 -2.0 的内容,您需要从 Fractional.one 手动组装它们或使用Fractional.fromInt

另一件值得指出的事情是 math.Fractional.ImplicitsOrdering.Implicits 的使用,这将允许您使用正常的数学语法(+、<、/等),而不是调用 plusdiv 等函数。

关于scala - Scala Numeric[T] 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13839022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com