Skip to content

Commit

Permalink
IMP解决浮点数精度问题,fraction增加精度参数 (#204)
Browse files Browse the repository at this point in the history
Co-authored-by: zhangsonglei <[email protected]>
  • Loading branch information
zhangsonglei and zhangsonglei authored Sep 20, 2023
1 parent dd03adc commit dfbad0f
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ case object Fraction extends Dimension with Rules {
override val dimDependents: List[Dimension] = List(Numeral)
}

case class FractionData(n: Double, numerator: Double, denominator: Double) extends NumeralValue with Resolvable {
case class FractionData(n: Double, numerator: Double, denominator: Double, numeratorPrecision: Int, denominatorPrecision: Int, precision: Option[Int] = None) extends NumeralValue with Resolvable {

override def resolve(context: Types.Context,
options: Types.Options): Option[(FractionData, Boolean)] =
(FractionData(n, numerator: Double, denominator: Double), false)
(FractionData(n, numerator, denominator, numeratorPrecision, denominatorPrecision, precision), false)

override def schema: Option[String] =
if (numerator * denominator >= 0) Some(s"$numerator/$denominator")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ trait Rules extends DimRules {
pattern = List(isDimension(Numeral).predicate, "分之".regex, isPositive.predicate),
prod = tokens {
case Token(_, n1: NumeralData) :: _ :: Token(_, n2: NumeralData) :: _ =>
val v = if (n1.value == 0) 0 else n2.value / n1.value
fraction(v, n2.value, n1.value)
val v = if (n1.value == 0) 0 else (BigDecimal.apply(n2.value)./(BigDecimal.apply(n1.value))).toDouble
fraction(v, n2.value, n1.value, n2.precision, n1.precision)
}
)

Expand All @@ -39,8 +39,8 @@ trait Rules extends DimRules {
pattern = List(isDimension(Numeral).predicate, "/".regex, isDimension(Numeral).predicate),
prod = tokens {
case Token(_, n1: NumeralData) :: _ :: Token(_, n2: NumeralData) :: _ =>
val v = if (n2.value == 0) 0 else n1.value / n2.value
fraction(v, n1.value, n2.value)
val v = if (n2.value == 0) 0 else (BigDecimal.apply(n1.value)./(BigDecimal.apply(n2.value))).toDouble
fraction(v, n1.value, n2.value, n1.precision, n2.precision)
}
)

Expand All @@ -50,12 +50,12 @@ trait Rules extends DimRules {
prod = tokens {
case Token(_, GroupMatch(_ :: s1 :: s2 :: _)) :: Token(_, n: NumeralData) :: _ =>
val neg = s1.nonEmpty
val scalar = s2 match {
case "" => if (neg) -100.0 else 100.0
case "" => if (neg) -1000.0 else 1000.0
case "" => if (neg) -10000.0 else 10000.0
val (scalar, precision) = s2 match {
case "" => if (neg) (-100.0, 2) else (100.0, 2)
case "" => if (neg) (-1000.0, 3) else (1000.0, 3)
case "" => if (neg) (-10000.0, 4) else (10000.0, 4)
}
fraction(n.value / scalar, n.value, scalar)
fraction((BigDecimal.apply(n.value)./(BigDecimal.apply(scalar))).toDouble, n.value, scalar, n.precision, 0, Some(n.precision + precision))
}
)

Expand All @@ -64,17 +64,17 @@ trait Rules extends DimRules {
pattern = List(isDimension(Numeral).predicate, "(%|‰)".regex),
prod = tokens {
case Token(_, n: NumeralData) :: Token(_, GroupMatch(s :: _)) :: _ =>
val scalar = s match {
case "%" => 0.01
case "" => 0.001
val (scalar, precision) = s match {
case "%" => (0.01, 2)
case "" => (0.001, 3)
}
fraction(n.value * scalar, n.value, 1/scalar)
fraction((BigDecimal.apply(n.value).*(BigDecimal.apply(scalar))).toDouble, n.value, 1/scalar, n.precision, 0, Some(n.precision + precision))
}
)

val oneHalf =
Rule(name = "<1> half", pattern = List(isIntegerBetween(1, 1).predicate, "".regex), prod = tokens {
case _ => fraction(0.5, 50.0, 100.0)
case _ => fraction(0.5, 50.0, 100.0, 0, 0, Some(2))
})

val hundredPercentRule = Rule(
Expand All @@ -84,7 +84,7 @@ trait Rules extends DimRules {
case Token(RegexMatch, GroupMatch(_ :: m :: _)) :: _ =>
val scalar = if (m.nonEmpty) -100.0 else 100.0
val value = 100.0 / scalar
fraction(value, 100.0, scalar)
fraction(value, 100.0, scalar, 0, 0, Some(2))
}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ package com.xiaomi.duckling.dimension.numeral
import com.xiaomi.duckling.Types.Token

package object fraction {
def fraction(v: Double, numerator: Double, denominator: Double): Token = Token(Fraction, FractionData(v, numerator, denominator))
def fraction(v: Double, numerator: Double, denominator: Double, numeratorPrecision: Int, denominatorPrecision: Int, precision: Option[Int] = None): Token = Token(Fraction, FractionData(v, numerator, denominator, numeratorPrecision, denominatorPrecision, precision))
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,21 @@ object Examples extends DimExamples {

override def pairs: List[(Types.ResolvedValue, List[String])] =
List(
(0.6, 60.0, 100.0, List("百分之六十")),
(0.6, 600.0, 1000.0, List("千分之六百")),
(0.75, 3.0, 4.0, List("4分之3", "四分之3", "3/4")),
(0.5, 64.0, 128.0, List("一百二十八分之64")),
(0.5, 50.0, 100.0, List("一半", "50%", "五十%")),
(0.5, 60.0, 120.0, List("六十/一百二十")),
(-0.6, 60.0, -100.0, List("负百分之六十", "负的百分之六十")),
(-1.0, 100.0, -100.0, List("负百分之百", "负的百分之百", "负的百分之一百")),
(1.0, 100.0, 100.0, List("百分之一百", "百分百", "百分之百"))
(0.6, 60.0, 100.0, 0, 0, Some(2), List("百分之六十")),
(0.7, 70.0, 100.0, 0, 0, Some(2), List("70%")),
(0.6, 600.0, 1000.0, 0, 0, Some(3), List("千分之六百")),
(0.75, 3.0, 4.0, 0, 0, None, List("4分之3", "四分之3", "3/4")),
(0.5, 64.0, 128.0, 0, 0, None, List("一百二十八分之64")),
(0.5, 50.0, 100.0, 0, 0, Some(2), List("一半", "50%", "五十%")),
(0.5, 60.0, 120.0, 0, 0, None, List("六十/一百二十")),
(-0.6, 60.0, -100.0, 0, 0, Some(2), List("负百分之六十", "负的百分之六十")),
(-1.0, 100.0, -100.0, 0, 0, Some(2), List("负百分之百", "负的百分之百", "负的百分之一百")),
(1.0, 100.0, 100.0, 0, 0, Some(2), List("百分之一百", "百分百", "百分之百")),
(0.5, 1.5, 3.0, 1, 0, None, List("三分之一点五", "1.5/3")),
(0.1562, 15.62, 100.0, 2, 0, Some(4), List("百分之十五点六二", "15.62%")),
(0.2, 2.5, 12.5, 1, 1, None, List("十二点五分之二点五", "2.5/12.5"))
).map {
case (expected, numerator, denominator, texts) => (FractionData(expected, numerator, denominator), texts)
case (expected, numerator, denominator, numeratorPrecision, denominatorPrecision, precision, texts) => (FractionData(expected, numerator, denominator, numeratorPrecision, denominatorPrecision, precision), texts)
}

override val dimension: Dimension = Fraction
Expand Down

0 comments on commit dfbad0f

Please sign in to comment.