Заключение В рамках данной дипломной работы была разработана система для обучения и проверки полученных знаний в объёме темы «Быстрое умножение чисел».
Система позволяет пользователю работать в двух режимах: режиме обучения и режиме тестирования. В режиме обучения непосредственно при вводе в качестве подсказки отображается правильность заполнения полей, не ведётся контроль времени, потраченного на решение, а также результаты не отсылаются на сервер хранения оценок; таким образом, в режиме обучения программа способна работать локально, и студент может упражняться в решении задач в любое время и на любом компьютере, даже не подключенном к сети Интернет.
В режиме тестирования время, отводимое на решение работы, составляет 30 минут, подсказок о правильности решения пользователю не даётся, и после завершения решения вычисляется оценка, и результаты отправляются на сервер. При этом подключение к серверу осуществляется через сеть Интернет, но также может осуществляться с любого компьютера.
Программный продукт был протестирован при помощи студентов, проходящих курс «Теория сложности вычислительных процессов и структур». В результате тестирования был доработан пользовательский интерфейс, способ отображения ошибок при вводе, а также был скорректирован алгоритм вычисления итоговой оценки.
Разработанное приложение значительно экономит время преподавателя, раньше тратившееся на детальный просмотр всех контрольных работ студентов. Таким образом, автор данной работы успешно достиг её основной цели.
Приложение А Библиография
Джеффри Рихтер. CLR via C#. Программирование на платформе Microsoft .NET Framework 2.0 на языке C#. — Питер, 2007. — 656 с.
Эндрю Троелсен. Язык программирования C# 2010 и платформа .NET 4. — Вильямс, 2011. — 1392 с.
Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектно-ориентированного проектирования. Паттерны проектирования. — Питер, 2007. — 366 с.
Фаулер М. Рефакторинг. Улучшение существующего кода. — Символ-Плюс, 2008. — 432 с.
Wikipedia, the free encyclopedia [Электронный ресурс] : Cвободная общедоступная многоязычная универсальная энциклопедия. — Режим доступа: http://en.wikipedia.org/wiki/Main_Page. — Загл. с экрана. — яз. англ.
А. А. Рубан, Т. Э. Разинкина. Теория сложности вычислительных процессов и структур: Методические указания/СибГУТИ. — Новосибирск, 2006. — 90 с.
Н.О.Прокофьева. Вопросы организации компьютерного контроля знаний. — Educational Technology & Society 9(1), 2006.
Приложение Б Исходные коды программ В связи с тем, что исходный код имеет слишком большой объём, в приложении Б размещены только основные модули.
// KaratsubaTenBaseSolver.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using DigitalDuality.Numerics; namespace DigitalDuality.GraduateWork
{
[DebuggerDisplay( "{VariableName} = {Expression} = {Result}" )]
public class SolverStep
{
public string VariableName
{
get;
set;
} public string Expression
{
get;
set;
} public bool ExpressionEditable
{
get;
set;
} public bool ExpressionVisible
{
get;
set;
} public string Result
{
get;
set;
} public bool ResultEditable
{
get;
set;
} public bool ResultVisible
{
get;
set;
} public SolverStep( string variable, string expression, string result )
{
VariableName = variable;
Expression = expression;
Result = result;
ExpressionEditable = true;
ResultEditable = true;
}
} public class KaratsubaTenBaseSolver
{
private static readonly ulong[] s_powersOfTen; static KaratsubaTenBaseSolver()
{
ulong val = 1;
var list = new List();
do
{
list.Add( val );
val *= 10;
} while( val < UInt64.MaxValue / 10 );
s_powersOfTen = list.ToArray();
} private static ulong GetPowerOfTen( int power )
{
return s_powersOfTen[ power ];
} private List _steps; private int _stepIndex; public KaratsubaTenBaseSolver()
{
_steps = new List();
} public SolverStep[] GetSteps()
{
return _steps.ToArray();
} public ulong Multiply( ulong x, ulong y )
{
_steps.Clear();
_stepIndex = 0;
if( x == 0 || y == 0 )
return 0;
if( x == 1 )
return y;
if( y == 1 )
return x; if( x < 10 && y < 10 )
return x * y; var length = Math.Max( x.DigitLength(), y.DigitLength() );
return MultiplyInner( x, y, length );
} private static string Var( string variableName, int index )
{
return variableName + (index == 0 ? String.Empty : index.ToString());
} private void AddVarStep( string variableName, int index, ulong value, int numberLength )
{
_steps.Add( new SolverStep( Var( variableName, index ), String.Empty, value.ToString( "D" + numberLength ) ) { ExpressionEditable = false } );
} private void AddVarStep( string variableName, int index, string expression, string result )
{
var step = new SolverStep( Var( variableName, index ), expression, result ) { ResultEditable = true };
if( expression == result )
{
step.ResultVisible = false;
step.ResultEditable = false;
}
_steps.Add( step );
} private void AddBasicStep( int index, ulong val1, ulong val2 )
{
var varName = String.Format( "x{0}*y{0}", index == 0 ? String.Empty : index.ToString() );
var result = String.Format( "( a{0} * 10^k + b{0} )*( c{0} * 10^k + d{0})", index == 0 ? String.Empty : index.ToString() );
var step = new SolverStep( varName, String.Format( "{0}*{1}", val1, val2 ), result ) { ExpressionEditable = false, ResultEditable = false };
step.ResultVisible = true;
if( index == 0 )
{
step.ExpressionVisible = true;
}
_steps.Add( step );
} private void AddBasicStep( int index, string expr, string result )
{
var varName = String.Format( "x{0}*y{0}", index == 0 ? String.Empty : index.ToString() );
_steps.Add( new SolverStep( varName, expr, result ) { ResultEditable = true } );
} private ulong MultiplyInner( ulong x, ulong y, int digitLength )
{
int thisStepIndex = _stepIndex;
_stepIndex++; var halfLength = (digitLength + 1) / 2;
var halfShift = GetPowerOfTen( halfLength );
var fullShift = GetPowerOfTen( digitLength );
AddBasicStep( thisStepIndex, x, y );
var a = x / halfShift;
AddVarStep( "a", thisStepIndex, a, halfLength );
var b = x % halfShift;
AddVarStep( "b", thisStepIndex, b, halfLength );
var c = y / halfShift;
AddVarStep( "c", thisStepIndex, c, halfLength );
var d = y % halfShift;
AddVarStep( "d", thisStepIndex, d, halfLength ); var ab = a + b;
var cd = c + d;
ulong abcdU;
string expr;
expr = String.Format( "({0}+{1})*({2}+{3})", a, b, c, d );
if( halfLength == 1 && ab < halfShift && cd < halfShift )
{
abcdU = ab * cd;
AddVarStep( "U", thisStepIndex, expr, abcdU.ToString() );
}
else
{
AddVarStep( "U", thisStepIndex, expr, String.Format( "{0}*{1}", ab, cd ) );
abcdU = (ab >= halfShift || cd >= halfShift) ? MultiplyOverflow( ab, cd, digitLength ) : MultiplyInner( ab, cd, halfLength );
AddVarStep( "U", thisStepIndex, abcdU, 1 );
} expr = String.Format( "{0}*{1}", a, c );
ulong acV;
if( halfLength == 1 )
{
acV = a * c;
AddVarStep( "V", thisStepIndex, expr, acV.ToString() );
}
else
{
AddVarStep( "V", thisStepIndex, expr, expr );
acV = MultiplyInner( a, c, halfLength );
AddVarStep( "V", thisStepIndex, acV, 1 );
}
expr = String.Format( "{0}*{1}", b, d );
ulong bdW;
if( halfLength == 1 )
{
bdW = b * d;
AddVarStep( "W", thisStepIndex, expr, bdW.ToString() );
}
else
{
AddVarStep( "W", thisStepIndex, expr, expr );
bdW = MultiplyInner( b, d, halfLength );
AddVarStep( "W", thisStepIndex, bdW, 1 );
} var result = acV * fullShift + (abcdU - acV - bdW) * halfShift + bdW;
expr = String.Format( "{0}*10^{1}+({2}-{3}-{4})*10^{5}+{6}", acV, digitLength, abcdU, acV, bdW, halfLength, bdW );
AddBasicStep( thisStepIndex, expr, result.ToString() );
return result;
} private ulong MultiplyOverflow( ulong x, ulong y, int overflowedLength )
{
int thisStepIndex = _stepIndex;
_stepIndex++; var halfLength = (overflowedLength + 1) / 2;
var halfShift = GetPowerOfTen( halfLength );
var fullShift = GetPowerOfTen( overflowedLength );
AddBasicStep( thisStepIndex, x, y );
var a = x / halfShift;
AddVarStep( "a", thisStepIndex, a, halfLength );
var b = x % halfShift;
AddVarStep( "b", thisStepIndex, b, halfLength );
var c = y / halfShift;
AddVarStep( "c", thisStepIndex, c, halfLength );
var d = y % halfShift;
AddVarStep( "d", thisStepIndex, d, halfLength ); var ad = a == 1 ? d : 0;
var bc = c == 1 ? b : 0;
var u = ad + bc;
var expr = String.Format( "{0}*{1}+{2}*{3}", a, d, b, c );
AddVarStep( "U'", thisStepIndex, expr, u.ToString() );
var acV = a == 1 ? c : 0;
AddVarStep( "V", thisStepIndex, String.Format( "{0}*{1}", a, c ), acV.ToString() ); ulong bdW;
expr = String.Format( "{0}*{1}", b, d );
if( halfLength == 1 )
{
bdW = b * d;
AddVarStep( "W", thisStepIndex, expr, bdW.ToString() );
}
else
{
AddVarStep( "W", thisStepIndex, expr, expr );
bdW = MultiplyInner( b, d, halfLength );
AddVarStep( "W", thisStepIndex, bdW, 1 );
} var result = acV * fullShift + u * halfShift + bdW;
expr = String.Format( "{0}*10^{1}+{2}*10^{3}+{4}", acV, overflowedLength, u, halfLength, bdW );
AddBasicStep( thisStepIndex, expr, result.ToString() );
return result;
}
}
} // FormMain.cs
using System;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Windows.Forms;
using DigitalDuality.Numerics; namespace DigitalDuality.GraduateWork
{
public partial class FormMain: Form
{
private ulong _leftNumber;
private ulong _rightNumber;
private ulong _requiredAnswer;
private readonly KaratsubaTenBaseSolver _karatsuba;
private SolverStep[] _solverSteps;
private readonly Random _rnd;
private TimeSpan _timeLeft; public FormMain()
{
InitializeComponent();
_rnd = new Random();
_karatsuba = new KaratsubaTenBaseSolver();
_timeLeft = TimeSpan.FromMinutes( 30 );
} public static void GenerateNumbers( Random rnd, ref ulong val1, ref ulong val2 )
{
const int lowerBound = 1000;
const int upperBound = 10000;
do
{
val1 = ( ulong )rnd.Next( lowerBound, upperBound );
} while( val1.ToString().IndexOf( '0' ) >= 0 ); do
{
val2 = ( ulong )rnd.Next( lowerBound, upperBound );
} while( val2.ToString().IndexOf( '0' ) >= 0 );
} private void FormMain_Load( object sender, EventArgs e )
{
var formLogin = new FormLogin();
formLogin.ShowDialog();
outUser.Text = String.IsNullOrEmpty( Settings.User ) ? "(обучение)" : Settings.User;
GenerateNumbers( _rnd, ref _leftNumber, ref _rightNumber );
StartTest();
} private void StartTest()
{
if(Settings.Mode != UserMode.Learn)
timerTimeout.Enabled = true;
_timeLeft = TimeSpan.FromMinutes( 30 ); //outTask.Text = String.Format( "{0} * {1} = ?", _leftNumber, _rightNumber );
_requiredAnswer = _leftNumber * _rightNumber;
var test = _karatsuba.Multiply( _leftNumber, _rightNumber );
Trace.Assert( _requiredAnswer == test ); _solverSteps = _karatsuba.GetSteps(); inAnswer.ResetBackColor();
inAnswer.Enabled = true;
tableLayoutPanelSteps.Enabled = true;
inAnswer.Text = String.Empty;
outRightAnswer.Text = "_";
outMark.Text = "_";
cmdAnswer.Enabled = true;
tableLayoutPanelSteps.SuspendLayout();
tableLayoutPanelSteps.Controls.Clear();
tableLayoutPanelSteps.RowCount = _solverSteps.Length;
for( int i = 0; i < _solverSteps.Length; i++ )
{
var step = _solverSteps[ i ];
var uc = new ControlStep
{
Name = "panelStep" + i,
varStep = { Text = step.VariableName, Tag = step.VariableName, ReadOnly = true },
exprStep = { Tag = step.Expression, ReadOnly = !step.ExpressionEditable },
resultStep = { Tag = step.Result, ReadOnly = !step.ResultEditable }
};
if( step.ExpressionVisible )
uc.exprStep.Text = step.Expression;
if( step.ResultVisible )
uc.resultStep.Text = step.Result; if( step.ExpressionEditable )
{
uc.exprStep.LostFocus += textBox_Leave;
outTooltip.SetToolTip( uc.exprStep, step.Expression );
}
if( step.ResultEditable )
{
uc.resultStep.LostFocus += textBox_Leave;
outTooltip.SetToolTip(uc.resultStep, step.Result);
}
tableLayoutPanelSteps.Controls.Add( uc, 0, i );
}
var size = this.Size;
tableLayoutPanelSteps.ResumeLayout();
size.Width += 100;
this.Size = size;
//Application.DoEvents();
size.Width -= 100;
this.Size = size;
} private void textBox_Leave( object sender, EventArgs e )
{
var textBox = ( TextBox )sender;
var tag = ( string )textBox.Tag;
if( !ExpressionHelper.AreExpressionsEqual( textBox.Text, tag ) )
{
textBox.BackColor = Color.Red;
}
else
{
textBox.ResetBackColor();
}
} private void menuExit_Click( object sender, EventArgs e )
{
Application.Exit();
} private void menuAbout_Click( object sender, EventArgs e )
{
new FormAbout().ShowDialog( this );
} private void timerTimeout_Tick( object sender, EventArgs e )
{
var t = ( Timer )sender;
|