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