| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- // tools/mixed_variance.dart
- import 'package:flutter/material.dart';
- import 'package:rational/rational.dart';
- import '../utils/math_utils.dart';
- class MixedVariancePage extends StatefulWidget {
- @override
- _MixedVariancePageState createState() => _MixedVariancePageState();
- }
- class _MixedVariancePageState extends State<MixedVariancePage> {
- final TextEditingController sampleSizesController = TextEditingController();
- final TextEditingController meansController = TextEditingController();
- final TextEditingController variancesController = TextEditingController();
- String result = '';
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(title: Text('混合方差')),
- body: Padding(
- padding: EdgeInsets.all(16),
- child: Column(
- children: [
- _buildInputField('各层样本量(用空格分隔)', sampleSizesController),
- _buildInputField('各层均值(用空格分隔)', meansController),
- _buildInputField('各层方差(用空格分隔)', variancesController),
- SizedBox(height: 20),
- ElevatedButton(
- onPressed: _calculate,
- child: Text('计算'),
- ),
- SizedBox(height: 20),
- if (result.isNotEmpty)
- Card(
- child: Padding(
- padding: EdgeInsets.all(16),
- child: Text(
- result,
- style: TextStyle(fontSize: 16),
- ),
- ),
- ),
- ],
- ),
- ),
- );
- }
- Widget _buildInputField(String label, TextEditingController controller) {
- return Padding(
- padding: EdgeInsets.symmetric(vertical: 8),
- child: TextField(
- controller: controller,
- keyboardType: TextInputType.numberWithOptions(signed: true, decimal: true),
- decoration: InputDecoration(
- labelText: label,
- border: OutlineInputBorder(),
- hintText: label.contains('分隔') ? '用空格分隔多个值' : '输入分数如: 1/2 或小数',
- ),
- ),
- );
- }
- void _calculate() {
- try {
- final sizes = sampleSizesController.text.split(' ').map((s) => MathUtils.parseRational(s)).toList();
- final means = meansController.text.split(' ').map((s) => MathUtils.parseRational(s)).toList();
- final variances = variancesController.text.split(' ').map((s) => MathUtils.parseRational(s)).toList();
- if (sizes.length != means.length || sizes.length != variances.length) {
- setState(() {
- result = '错误: 输入的数据长度不一致';
- });
- return;
- }
- Rational totalSize = Rational.zero;
- Rational weightedSum = Rational.zero;
- for (int i = 0; i < sizes.length; i++) {
- totalSize += sizes[i];
- weightedSum += sizes[i] * means[i];
- }
- final overallMean = weightedSum / totalSize;
- Rational mixedVariance = Rational.zero;
- for (int i = 0; i < sizes.length; i++) {
- mixedVariance += sizes[i] * (variances[i] + (means[i] - overallMean).pow(2)) / totalSize;
- }
- // 获取近似值
- double overallMeanApprox = overallMean.toDouble();
- double mixedVarianceApprox = mixedVariance.toDouble();
- setState(() {
- result = '总均值 = ${MathUtils.rationalToString(overallMean)} (≈${overallMeanApprox.toStringAsFixed(4)})\n'
- '混合方差 = ${MathUtils.rationalToString(mixedVariance)} (≈${mixedVarianceApprox.toStringAsFixed(4)})';
- });
- } catch (e) {
- setState(() {
- result = '错误: $e';
- });
- }
- }
- @override
- void dispose() {
- sampleSizesController.dispose();
- meansController.dispose();
- variancesController.dispose();
- super.dispose();
- }
- }
|