Browse Source

Simplify '3% · kg' to '0.03 kg'

see #89
David Peter 2 years ago
parent
commit
03c7e7c142
2 changed files with 35 additions and 8 deletions
  1. 26 8
      numbat/src/quantity.rs
  2. 9 0
      numbat/src/unit.rs

+ 26 - 8
numbat/src/quantity.rs

@@ -154,14 +154,24 @@ impl Quantity {
                         .then(f1.exponent.cmp(&f2.exponent))
                 })
                 .expect("At least one unit factor in the group");
-            let exponent = group_as_unit
-                .iter()
-                .map(|f| f.exponent * removed_exponent(f) / removed_exponent(group_representative))
-                .sum();
-            let target_unit = Unit::from_factor(UnitFactor {
-                exponent,
-                ..group_representative.clone()
-            });
+
+            let target_unit = if group_as_unit.to_base_unit_representation().0.is_scalar() {
+                // If the group-representative is convertible to a scalar,
+                // use 'scalar' as the target unit instead. This allows us
+                // to simplify, for example, '3% · kg' to '0.03 kg'.
+                Unit::scalar()
+            } else {
+                let exponent = group_as_unit
+                    .iter()
+                    .map(|f| {
+                        f.exponent * removed_exponent(f) / removed_exponent(group_representative)
+                    })
+                    .sum();
+                Unit::from_factor(UnitFactor {
+                    exponent,
+                    ..group_representative.clone()
+                })
+            };
 
             let converted = Quantity::from_unit(group_as_unit)
                 .convert_to(&target_unit)
@@ -414,6 +424,14 @@ mod tests {
         }
     }
 
+    #[test]
+    fn full_simplify_scalarlike_units() {
+        {
+            let q = Quantity::new_f64(3.0, Unit::percent() * Unit::kilogram());
+            assert_eq!(q.full_simplify(), Quantity::new_f64(0.03, Unit::kilogram()));
+        }
+    }
+
     #[test]
     fn full_simplify_complex() {
         {

+ 9 - 0
numbat/src/unit.rs

@@ -163,6 +163,10 @@ impl Unit {
         Self::unity()
     }
 
+    pub fn is_scalar(&self) -> bool {
+        self == &Self::scalar()
+    }
+
     pub fn new_base(name: &str, canonical_name: &str) -> Self {
         Unit::from_factor(UnitFactor {
             prefix: Prefix::none(),
@@ -287,6 +291,11 @@ impl Unit {
         )
     }
 
+    #[cfg(test)]
+    pub fn percent() -> Self {
+        Self::new_derived("percent", "%", Number::from_f64(1e-2), Self::scalar())
+    }
+
     #[cfg(test)]
     pub fn hertz() -> Self {
         Self::new_derived(