比较两个数字 [英] Compare two numbers
问题描述
我如何比较两个数字。任何数字。像 Int
和 Float
?我没有兴趣与复数或类似的东西比较。我只想比较那些可比较的。 Float和Int是。
假设您有:
def compareTwoNumbers [???](array:Array [???],number:???)= {
array(0)>数字//这必须编译
}
我写什么而不是<$ c
-
Number
。 -
T <:Number
数字(对不起,我不明白在这种情况下如何使用它,没有任何示例/文档也是如此我认为主要的问题是数字类型的转换。我认为主要的问题是数字类型的转换。所以让我们编码一下:
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' :Y
}
当然必须指定抽象概念:(例如)
隐式对象Int2IntNumericConversion扩展
}
隐式对象Double2DoubleNumericConversion扩展NumericConversion [Double,Double] {
def convert(d:Double):Double = d
}
隐式对象Int2DoubleNumericConversion extends NumericConversion [ Int,Double] {
def convert(i:Int):Double = i.toDouble
}
现在比较方法如下:
def compareTwoNumbers1 [N1,N2,N3](n1: N1,n2:N2)
(隐式conv1:NumericConversion [N1,N3],
conv2:NumericConversion [N2,N3],
ord:Ordering [N3]):Int = {
ord compare(conv1 convert n1,conv2 convert n2)
}
用法:
compareTwoNumbers1 [Int,Double,Double](3,8D)/ / -1
多么可惜,我们必须明确地声明类型参数,所以我试过:
def compareTwoNumbers2 [N3] = new {
def apply [N1,N2](n1:N1,n2:N2 )(隐式conv1:NumericConversion [N1,N3],
conv2:NumericConversion [N2,N3],
ord:Ordering [N3]):Int = {
ord compare(conv1 convert n1 ,conv2转换成n2)
}
}
:
compareTwoNumbers2 [Double](3,8D)// -1
不满意,所以我试过了:
trait NumericUpperBound [Num1,Nu m2,UpperBound]
隐式对象NumericUpperBoundIDD扩展NumericUpperBound [Int,Double,Double]
隐式对象NumericUpperBoundDID扩展NumericUpperBound [Double,Int,Double]
使用新的比较方法:
def compareTwoNumbers3 [N1, N2,N3](n1:N1,n2:N2)
(隐式nub:NumericUpperBound [N1,N2,N3],
conv1:NumericConversion [N1,N3],
conv2:NumericConversion [N2,N3],
ord:Ordering [N3]):Int = {
ord compare(conv1 convert n1,conv2 convert n2)
}
$ c $compareTwoNumbers3( 3,8D)// -1
当然,必须创建所有基元的类型类。但可以灵活地将它扩展到
BigInt
等等。
编辑
由@wvxvw提到的提到
NumericUpperBounds
矩阵的评论激励我规避矩阵,这里是一个正在运行的示例(当前不包括Byte
和Short
):
trait ==> [X,Y] extends(X => Y)
object ==> {
def apply [X,Y](f:X => Y):X ==> Y = {
new(X ==> Y){
def apply(x:X):Y = f(x)
}
}
}
隐式val Int2LongNumericConversion = ==> {x:Int => x.toLong}
隐式val Int2FloatNumericConversion = ==> {x:Int => x.toFloat}
隐式val Int2DoubleNumericConversion = ==> {x:Int => x.toDouble}
隐式val Long2FloatNumericConversion = ==> {x:Long => x.toFloat}
隐式val Long2DoubleNumericConversion = ==> {x:Long => x.toDouble}
隐式val Float2DoubleNumericConversion = ==> {x:Float => x.toDouble}
implicit def reflexiveNumericConversion [X]:X ==> X = new(X ==> X){def apply(x:X):X = x}
trait NumericUpperBound [Num1,Num2,UpperBound]
implicit def reflexiveNumericUpperBound [X]:NumericUpperBound [X,X,X] = new NumericUpperBound [X,X,X] {}
隐式def inductiveNumericUpperBound1 [X,Y](implicit ev:X ==> Y): NumericUpperBound [Y,X,Y] = new NumericUpperBound [Y,X,Y] {}
隐式def inductiveNumericUpperBound2 [X,Y](隐式ev:X ==> Y):NumericUpperBound [X,Y, Y] = new NumericUpperBound [X,Y,Y] {}
def compareTwoNumbers [N1,N2,N3](n1:N1,n2:N2)
(隐式nub:NumericUpperBound [ N1,N2,N3],
conv1:N1 ==> N3,
conv2:N2 ==> N3,
ord:Ordering [N3]):Int = {
ord compare(n1,n2)
}
compareTwoNumbers(9L,13)// -1
How do I compare two numbers. Any numbers. Like
Int
andFloat
? I'm not interested in comparing with complex numbers or anything like that. I only want to compare those, which are comparable. Float and Int are.Suppose you have:
def compareTwoNumbers[???](array:Array[???], number:???) = { array(0) > number // this has to compile }
What do I write instead of
???
?Things I've tried so far:
Number
.T <: Number
Numeric
(Sorry, I don't understand how to use it in this situation, no examples / documentation is too poor).
解决方案I think the main problem is the conversion of numeric types. So let´s encode that:
trait NumericConversion[X, Y] { def convert(x: X): Y }
Of course one have to specify that abstract concept: (for example)
implicit object Int2IntNumericConversion extends NumericConversion[Int, Int] { def convert(i: Int): Int = i } implicit object Double2DoubleNumericConversion extends NumericConversion[Double, Double] { def convert(d: Double): Double = d } implicit object Int2DoubleNumericConversion extends NumericConversion[Int, Double] { def convert(i: Int): Double = i.toDouble }
Now the comparing method goes as follows:
def compareTwoNumbers1[N1, N2, N3](n1: N1, n2: N2) (implicit conv1: NumericConversion[N1, N3], conv2: NumericConversion[N2, N3], ord: Ordering[N3]): Int = { ord compare (conv1 convert n1, conv2 convert n2) }
Usage:
compareTwoNumbers1[Int, Double, Double](3, 8D) // -1
What a pitty, we have to explicitly state the type parameters, so I tried:
def compareTwoNumbers2[N3] = new { def apply[N1, N2](n1: N1, n2: N2)(implicit conv1: NumericConversion[N1, N3], conv2: NumericConversion[N2, N3], ord: Ordering[N3]): Int = { ord compare (conv1 convert n1, conv2 convert n2) } }
That reduces to one type argument:
compareTwoNumbers2[Double](3, 8D) // -1
Not satisfying, so I tried this:
trait NumericUpperBound[Num1, Num2, UpperBound] implicit object NumericUpperBoundIDD extends NumericUpperBound[Int, Double, Double] implicit object NumericUpperBoundDID extends NumericUpperBound[Double, Int, Double]
With a new comparing method:
def compareTwoNumbers3[N1, N2, N3](n1: N1, n2: N2) (implicit nub: NumericUpperBound[N1, N2, N3], conv1: NumericConversion[N1, N3], conv2: NumericConversion[N2, N3], ord: Ordering[N3]): Int = { ord compare (conv1 convert n1, conv2 convert n2) }
Now it works:
compareTwoNumbers3(3, 8D) // -1
Of course, type classes for all primitives must be created. But it´s flexible to extend it to
BigInt
, etc. later on.EDIT
The comment by @wvxvw which mentions a matrix of
NumericUpperBounds
inspired me to circumvent a matrix, here is a running example (excludingByte
andShort
for the moment):trait ==>[X, Y] extends (X => Y) object ==> { def apply[X, Y](f: X => Y): X ==> Y = { new (X ==> Y) { def apply(x: X): Y = f(x) } } } implicit val Int2LongNumericConversion = ==> { x: Int => x.toLong } implicit val Int2FloatNumericConversion = ==> { x: Int => x.toFloat } implicit val Int2DoubleNumericConversion = ==> { x: Int => x.toDouble } implicit val Long2FloatNumericConversion = ==> { x: Long => x.toFloat } implicit val Long2DoubleNumericConversion = ==> { x: Long => x.toDouble } implicit val Float2DoubleNumericConversion = ==> { x: Float => x.toDouble } implicit def reflexiveNumericConversion[X]: X ==> X = new (X ==> X) { def apply(x: X): X = x } trait NumericUpperBound[Num1, Num2, UpperBound] implicit def reflexiveNumericUpperBound[X]: NumericUpperBound[X, X, X] = new NumericUpperBound[X, X, X] {} implicit def inductiveNumericUpperBound1[X, Y](implicit ev: X ==> Y): NumericUpperBound[Y, X, Y] = new NumericUpperBound[Y, X, Y] {} implicit def inductiveNumericUpperBound2[X, Y](implicit ev: X ==> Y): NumericUpperBound[X, Y, Y] = new NumericUpperBound[X, Y, Y] {} def compareTwoNumbers[N1, N2, N3](n1: N1, n2: N2) (implicit nub: NumericUpperBound[N1, N2, N3], conv1: N1 ==> N3, conv2: N2 ==> N3, ord: Ordering[N3]): Int = { ord compare (n1, n2) } compareTwoNumbers(9L, 13) // -1
这篇关于比较两个数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!