| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- // tools/derivative_calculator.dart
- import 'package:flutter/material.dart';
- import 'package:math_expressions/math_expressions.dart';
- class DerivativeCalculatorPage extends StatefulWidget {
- @override
- _DerivativeCalculatorPageState createState() => _DerivativeCalculatorPageState();
- }
- class _DerivativeCalculatorPageState extends State<DerivativeCalculatorPage> {
- final TextEditingController _functionController = TextEditingController();
- final TextEditingController _pointController = TextEditingController();
- String _result = '';
- String _derivative = '';
- bool _showPointInput = false;
- @override
- void dispose() {
- _functionController.dispose();
- _pointController.dispose();
- super.dispose();
- }
- void _calculateDerivative() {
- final String functionText = _functionController.text.trim();
- if (functionText.isEmpty) {
- setState(() {
- _result = '请输入函数表达式';
- _derivative = '';
- });
- return;
- }
- try {
- // 解析函数表达式
- Parser p = Parser();
- Expression exp = p.parse(functionText);
- // 对x求导
- Expression deriv = exp.derive('x');
- // 简化导数表达式
- Expression simplifiedDeriv = deriv.simplify();
- setState(() {
- _derivative = '导函数: ${simplifiedDeriv.toString()}';
- // 如果用户要求计算某点的导数值
- if (_showPointInput && _pointController.text.isNotEmpty) {
- try {
- double point = double.parse(_pointController.text);
- ContextModel cm = ContextModel();
- cm.bindVariable(Variable('x'), Number(point));
- double value = simplifiedDeriv.evaluate(EvaluationType.REAL, cm);
- _result = '在 x = $point 处的导数值: ${value.toStringAsFixed(4)}';
- } catch (e) {
- _result = '点的格式错误,请输入有效的数字';
- }
- } else {
- _result = _derivative;
- }
- });
- } catch (e) {
- setState(() {
- _result = '表达式解析错误,请检查格式\n支持的格式示例: x^2 + 3*x + sin(x)';
- _derivative = '';
- });
- }
- }
- void _clearAll() {
- setState(() {
- _functionController.clear();
- _pointController.clear();
- _result = '';
- _derivative = '';
- });
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: Text('导数计算器', style: TextStyle(color: Colors.black)),
- backgroundColor: Colors.white,
- elevation: 1,
- actions: [
- IconButton(
- icon: Icon(Icons.info_outline),
- onPressed: () {
- _showInstructions();
- },
- ),
- ],
- ),
- body: Padding(
- padding: EdgeInsets.all(16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- '函数表达式 (以x为变量):',
- style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
- ),
- SizedBox(height: 8),
- TextField(
- controller: _functionController,
- decoration: InputDecoration(
- hintText: '例如: x^2 + 3*x + sin(x)',
- border: OutlineInputBorder(),
- suffixIcon: IconButton(
- icon: Icon(Icons.info),
- onPressed: _showExpressionHelp,
- ),
- ),
- ),
- SizedBox(height: 16),
- // 计算某点导数值的选项
- Row(
- children: [
- Checkbox(
- value: _showPointInput,
- onChanged: (value) {
- setState(() {
- _showPointInput = value!;
- if (!value) {
- _pointController.clear();
- }
- });
- },
- ),
- Text('计算某点处的导数值'),
- ],
- ),
- if (_showPointInput) ...[
- SizedBox(height: 8),
- Text(
- '输入点的x坐标:',
- style: TextStyle(fontSize: 14),
- ),
- SizedBox(height: 8),
- TextField(
- controller: _pointController,
- decoration: InputDecoration(
- hintText: '例如: 2.5',
- border: OutlineInputBorder(),
- ),
- keyboardType: TextInputType.numberWithOptions(decimal: true),
- ),
- ],
- SizedBox(height: 20),
- Row(
- children: [
- Expanded(
- child: ElevatedButton(
- onPressed: _calculateDerivative,
- style: ElevatedButton.styleFrom(
- backgroundColor: Colors.blue,
- padding: EdgeInsets.symmetric(vertical: 12),
- ),
- child: Text('计算导数', style: TextStyle(color: Colors.white)),
- ),
- ),
- SizedBox(width: 10),
- Expanded(
- child: ElevatedButton(
- onPressed: _clearAll,
- style: ElevatedButton.styleFrom(
- backgroundColor: Colors.grey,
- padding: EdgeInsets.symmetric(vertical: 12),
- ),
- child: Text('清空', style: TextStyle(color: Colors.white)),
- ),
- ),
- ],
- ),
- SizedBox(height: 20),
- if (_result.isNotEmpty) ...[
- Container(
- width: double.infinity,
- padding: EdgeInsets.all(16),
- decoration: BoxDecoration(
- color: Colors.grey[50],
- borderRadius: BorderRadius.circular(8),
- border: Border.all(color: Colors.grey[300]!),
- ),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- if (_derivative.isNotEmpty && _showPointInput) ...[
- Text(
- _derivative,
- style: TextStyle(fontSize: 14, color: Colors.grey[700]),
- ),
- SizedBox(height: 8),
- ],
- Text(
- _result,
- style: TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.bold,
- color: Colors.blue[800],
- ),
- ),
- ],
- ),
- ),
- ],
- Spacer(),
- _buildExamples(),
- ],
- ),
- ),
- );
- }
- Widget _buildExamples() {
- return Container(
- width: double.infinity,
- padding: EdgeInsets.all(16),
- decoration: BoxDecoration(
- color: Colors.blue[50],
- borderRadius: BorderRadius.circular(8),
- ),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- '表达式示例:',
- style: TextStyle(fontWeight: FontWeight.bold, color: Colors.blue[800]),
- ),
- SizedBox(height: 8),
- _buildExampleItem('x^2 + 3*x + 2'),
- _buildExampleItem('sin(x)'),
- _buildExampleItem('cos(x)'),
- _buildExampleItem('ln(x)'),
- _buildExampleItem('sqrt(x)'),
- _buildExampleItem('(x+1)/(x-1)'),
- ],
- ),
- );
- }
- Widget _buildExampleItem(String example) {
- return GestureDetector(
- onTap: () {
- setState(() {
- _functionController.text = example;
- });
- },
- child: Padding(
- padding: EdgeInsets.symmetric(vertical: 4),
- child: Text(
- '• $example',
- style: TextStyle(color: Colors.blue[700], fontSize: 14),
- ),
- ),
- );
- }
- void _showInstructions() {
- showDialog(
- context: context,
- builder: (context) => AlertDialog(
- title: Text('使用说明'),
- content: SingleChildScrollView(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisSize: MainAxisSize.min,
- children: [
- Text('1. 输入以x为自变量的函数表达式'),
- SizedBox(height: 8),
- Text('2. 支持的基本函数:'),
- Text(' • sin(x), cos(x), tan(x)'),
- Text(' • ln(x) - 自然对数'),
- Text(' • sqrt(x) - 平方根'),
- SizedBox(height: 8),
- Text('3. 支持的操作符:'),
- Text(' • +, -, *, /'),
- Text(' • ^ - 幂运算'),
- Text(' • () - 括号'),
- SizedBox(height: 8),
- Text('4. 可选计算某点处的导数值'),
- ],
- ),
- ),
- actions: [
- TextButton(
- onPressed: () => Navigator.pop(context),
- child: Text('确定'),
- ),
- ],
- ),
- );
- }
- void _showExpressionHelp() {
- showDialog(
- context: context,
- builder: (context) => AlertDialog(
- title: Text('表达式格式帮助'),
- content: SingleChildScrollView(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisSize: MainAxisSize.min,
- children: [
- Text('支持的数学表达式:'),
- SizedBox(height: 8),
- _buildHelpItem('x^2', 'x的平方'),
- _buildHelpItem('3*x', '3乘以x'),
- _buildHelpItem('sin(x)', '正弦函数'),
- _buildHelpItem('cos(x)', '余弦函数'),
- _buildHelpItem('ln(x)', '自然对数'),
- _buildHelpItem('sqrt(x)', '平方根'),
- _buildHelpItem('(x+1)/(x-1)', '分式'),
- ],
- ),
- ),
- actions: [
- TextButton(
- onPressed: () => Navigator.pop(context),
- child: Text('确定'),
- ),
- ],
- ),
- );
- }
- Widget _buildHelpItem(String expression, String description) {
- return Padding(
- padding: EdgeInsets.symmetric(vertical: 4),
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Container(
- width: 80,
- child: Text(
- expression,
- style: TextStyle(fontFamily: 'Monospace', fontWeight: FontWeight.bold),
- ),
- ),
- SizedBox(width: 10),
- Expanded(child: Text(description)),
- ],
- ),
- );
- }
- }
|