mixed_variance.dart 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. import 'package:flutter/material.dart';
  2. import 'tool_kit.dart';
  3. /// 混合方差 —— 工具页改造后的样板:输入框交给 [ToolScaffold],算式交给 Symja。
  4. ///
  5. /// 总均值 μ = Σ nᵢmᵢ / Σ nᵢ
  6. /// 混合方差 = Σ nᵢ(vᵢ + (mᵢ-μ)²) / Σ nᵢ
  7. ///
  8. /// 两个式子都要用到 μ,所以第二个式子把 μ 的定义整个代进去 —— 表达式长一点,
  9. /// 但省掉了"先算一次、把结果拼回表达式里"这种来回。Symja 求值一次就够。
  10. class MixedVariancePage extends StatefulWidget {
  11. const MixedVariancePage({super.key});
  12. @override
  13. State<MixedVariancePage> createState() => _MixedVariancePageState();
  14. }
  15. class _MixedVariancePageState extends State<MixedVariancePage> {
  16. // 字段要在 State 里建:主题一变(E-Ink、键盘弹出)页面会重建,
  17. // 建在 build 里的话控制器会被换掉,用户打的字就没了。
  18. final _sizes = ToolField('各层样本量 nᵢ', hint: '用空格分隔多个值');
  19. final _means = ToolField('各层均值 mᵢ', hint: '用空格分隔多个值');
  20. final _variances = ToolField('各层方差 vᵢ', hint: '用空格分隔多个值');
  21. @override
  22. Widget build(BuildContext context) => ToolScaffold(
  23. title: '混合方差',
  24. fields: [_sizes, _means, _variances],
  25. compute: (session) async {
  26. if (_sizes.count != _means.count ||
  27. _sizes.count != _variances.count) {
  28. throw Exception(
  29. '三组数据的个数必须一致(现在是 ${_sizes.count}、'
  30. '${_means.count}、${_variances.count})',
  31. );
  32. }
  33. final n = _sizes.list;
  34. final m = _means.list;
  35. final v = _variances.list;
  36. final mu = 'Total[$n*$m]/Total[$n]';
  37. final mixed = 'Total[$n*($v+($m-($mu))^2)]/Total[$n]';
  38. return [
  39. ...await exactAndApprox(session, '总均值 μ', mu),
  40. ...await exactAndApprox(session, '混合方差', mixed),
  41. ];
  42. },
  43. );
  44. }