1

想象一下,我在 Scala 中有 Imaginary(x) 类和 Real(y) 类。有没有办法做 ComplexNumber = 3 + 2i 而不是做 ComplexNumber = Real(3) + Imaginary(2) ?

谢谢。

4

4 回答 4

5

3 + 2.i了吗?

sealed trait ComplexNumber {
  val re: Int
  val im: Int
}

case class Real(re: Int) extends ComplexNumber { val im: Int = 0 }
implicit class ToReal(val re: Int) extends AnyVal {
  def +(that: Imaginary) = Mixed(re, that.im)
}

case class Imaginary(im: Int) extends ComplexNumber { val re: Int = 0 }
implicit class ToImaginary(val im: Int) extends AnyVal {
  def i: Imaginary = Imaginary(im)
}

case class Mixed(re: Int, im: Int) extends ComplexNumber

用法:

scala> 3 + 2.i
res3: Mixed = Mixed(3,2)
于 2013-06-29T17:45:52.573 回答
4

2i意味着2*i。您不能在 scala 中替换2*a2a,因此您应该使用 operator *

case class ComplexNumber(re: Int, im: Int){
  def +(that: ComplexNumber) = ComplexNumber(re + that.re, im + that.im)
  def -(that: ComplexNumber) = ComplexNumber(re - that.re, im - that.im)
  def *(that: ComplexNumber) = ComplexNumber(re*that.re - im*that.im, re*that.im + im*that.re)
}
implicit def intToComplec(i: Int): ComplexNumber = ComplexNumber(i, 0)
object I extends ComplexNumber(0, 1)

用法:

scala> 3 + 2*I
res0: ComplexNumber = ComplexNumber(3,2)

scala> 4 - I
res1: ComplexNumber = ComplexNumber(4,-1)
于 2013-07-01T13:33:11.657 回答
2

当心。请记住,复数的实部和虚部都必须是实数。你能做类似的事情:

case class Complex(real: Real, imag: Real) {
  // in here define all your arithmetic ops
}

然后,您可以使用 senia 的隐式技巧将数字自动转换为实数,并声明一个将其转换为虚数的i方法。Real

// inside Real
def i: Complex = Complex(Real(0), this)

我只是提醒你不要让代码过于复杂,只是为了可爱的语法。Complex(a, b)很好很清楚。如果您想创建解析器,请随意,但我会将其保留为String值并让代码成为代码。

于 2013-06-29T18:27:15.143 回答
1

不,这是不可能的。编译器的词法分析阶段“拥有”数字字符串的后缀,例如f( Float)、d( Double) 和l( Long),并且这种表示法没有可扩展性。

您可能想考虑使用新的字符串插值机制来注释常量。您必须接受解析它们,并且如果您愿意,“标志”(您的i)必须用于前缀位置。这会给你这样的东西:

val imaginary = i"1.2+3.4i"

我不了解新编译器中宏的功能,但也许您可以在编译时完成解析,这将排除在运行时尝试使用格式错误的值。

这种方法(无论是编译时解析还是运行时解析)将是灵活的(只要您可以在接受的格式中随心所欲地适应),但它显然与人们在数学文本中使用的符号不匹配。

于 2013-06-29T16:41:36.057 回答