| | | @@ 変更前 1行目〜 / 変更後 1行目〜 @@ |
| 1 | 1 | | //! だし(出汁)の割合計算。 |
| 2 | | − | //! v1: 水の量 × (割合 ÷ 100) を f64 で計算し、(n * 10.0).round() / 10.0 で小数第1位に丸める素直な書き方。 |
| 2 | + | //! v2: 0.1g を単位にした整数(i64)で計算する。水の量 × 割合 ÷ 100 を 0.1g 単位で四捨五入 = (水 × 割合 × 10 + 50) / 100(整数の割り算)。 |
| 3 | + | //! f64 だと 45 × 0.03 が 1.3499999999999999 になり、round で 1.3 に落ちる(f64::round 自体は 0.5 を大きい方へ丸める)。 |
| 3 | 4 | | |
| 4 | 5 | | use crate::json::{obj, s, Value}; |
| 5 | 6 | | |
| 6 | | − | fn materials(kind: &str) -> Option<&'static [(&'static str, f64)]> { |
| 7 | + | fn materials(kind: &str) -> Option<&'static [(&'static str, i64)]> { |
| 7 | 8 | | match kind { |
| 8 | | − | "ichiban" => Some(&[("昆布", 1.0), ("かつお節", 2.0)]), |
| 9 | | − | "katsuo" => Some(&[("かつお節", 3.0)]), |
| 10 | | − | "konbu" => Some(&[("昆布", 2.0)]), |
| 11 | | − | "niboshi" => Some(&[("煮干し", 3.0)]), |
| 12 | | − | "karyu" => Some(&[("顆粒だし", 1.0)]), |
| 9 | + | "ichiban" => Some(&[("昆布", 1), ("かつお節", 2)]), |
| 10 | + | "katsuo" => Some(&[("かつお節", 3)]), |
| 11 | + | "konbu" => Some(&[("昆布", 2)]), |
| 12 | + | "niboshi" => Some(&[("煮干し", 3)]), |
| 13 | + | "karyu" => Some(&[("顆粒だし", 1)]), |
| 13 | 14 | | _ => None, |
| 14 | 15 | | } |
| 15 | 16 | | } |
| 16 | 17 | | |
| 17 | | − | fn gram(x: f64) -> String { |
| 18 | | − | format!("{}", (x * 10.0).round() / 10.0) |
| 18 | + | /// 水 × 割合 ÷ 100 を 0.1g 単位で四捨五入して書く(水は 1 以上) |
| 19 | + | fn gram(water_ml: i64, pct: i64) -> String { |
| 20 | + | let tenths = (water_ml * pct * 10 + 50) / 100; |
| 21 | + | if tenths % 10 == 0 { format!("{}", tenths / 10) } else { format!("{}.{}", tenths / 10, tenths % 10) } |
| 19 | 22 | | } |
| 20 | 23 | | |
| 21 | 24 | | pub fn calc(water_ml: i64, kind: &str) -> Result<Value, String> { |
| | | @@ 変更前 23行目〜 / 変更後 26行目〜 @@ |
| 23 | 26 | | return Ok(obj(vec![("error", s("invalid_input"))])); |
| 24 | 27 | | } |
| 25 | 28 | | let list = materials(kind).ok_or(format!("unknown type: {kind}"))?; |
| 26 | | − | let out = list |
| 27 | | − | .iter() |
| 28 | | − | .map(|(name, pct)| obj(vec![("name", s(*name)), ("grams", s(gram(water_ml as f64 * (pct / 100.0))))])) |
| 29 | | − | .collect(); |
| 29 | + | let out = list.iter().map(|(name, pct)| obj(vec![("name", s(*name)), ("grams", s(gram(water_ml, *pct)))])).collect(); |
| 30 | 30 | | Ok(obj(vec![("materials", Value::Arr(out))])) |
| 31 | 31 | | } |