Цепные дроби на службе человечества...
Mar. 6th, 2020 01:57 amКак-то уже писал про цепные дроби (continued fraction)
https://febb.livejournal.com/3541286.html
Подогнал точность часиков.
Точнее измерил частоту кварца с помощью двух немного скрученных проволочек
(чтобы сделать маленькую разделительную емкость)
и осциллографа. Получилось: 3.58282 MHz
Ну какой-то старый кварц откуда не помню.
Но это как вино, чем старее, тем лучше? :)
Получается в минуту переполнение 8 битного таймера с 256 делителем:
3.58282 * 1000,000 / 4 / 256 / 256 * 60 = 820.04241943359375 / мин.
Это число нужно как можно более точно представить в виде 16 битного счетчика,
потому, что в часах 8-битный процессор и его надо жалеть и холить. :)
Для этой цели нужно, как мне подсказали использовать эти самые цепные дроби.
Написал небольшую .NET программку (в ссылке выше) и получилось такое:
0) 820 : 820 / 1 = 820 diff: 0.04241943359375
1) 23 : 18861 / 23 = 820.0434782608695652173913043 diff: -0.0010588272758152173913043
2) 1 : 19681 / 24 = 820.0416666666666666666666667 diff: 0.0007527669270833333333333
3) 1 : 38542 / 47 = 820.0425531914893617021276596 diff: -0.0001337578956117021276596
4) 2 : 96765 / 118 = 820.0423728813559322033898305 diff: 0.0000465522378177966101695
5) 1 : 135307 / 165 = 820.0424242424242424242424242 diff: -0.0000048088304924242424242
6) 6 : 908607 / 1108 = 820.0424187725631768953068592 diff: 0.0000006610305731046931408
7) 1 : 1043914 / 1273 = 820.0424194815396700706991359 diff: -0.0000000479459200706991359
8) 11 : 12391661 / 15111 = 820.0424194295546290781549864 diff: 0.0000000040391209218450136
9) 1 : 13435575 / 16384 = 820.04241943359375 diff: 0.00000000000000
Поэтому взял 3) 38542 / 47 = 820.04255319 diff: -0.000133
Это конечно хорошо, но вдруг в диапазоне 38542-65535 есть лучшее приближение?
Хотя точность 0.1 миллионная это 1 секунда за 116 дней - это неплохо
и вряд ли кварц стабильнее.
Но все же таки задача открыта - как без перебора найти наилучшую дробь,
числитель или знаменатель не превышает данное число?
Хотя перебрать несложно - нужно просто увеличивать знаменатель с 47 до 79 и найти
наименьшую погрешность...
Может кому-то нужна программка, которая считает цепные дроби, дарю бизвазмездна:
P.S. Кстати омереканские блюстители времени обновили сайт:
https://time.gov/
Стало веселее и наряднее. Прямо как бабский сарафан какой-то.
Празднек в каждую избу! :)
https://febb.livejournal.com/3541286.html
Подогнал точность часиков.
Точнее измерил частоту кварца с помощью двух немного скрученных проволочек
(чтобы сделать маленькую разделительную емкость)
и осциллографа. Получилось: 3.58282 MHz
Ну какой-то старый кварц откуда не помню.
Но это как вино, чем старее, тем лучше? :)
Получается в минуту переполнение 8 битного таймера с 256 делителем:
3.58282 * 1000,000 / 4 / 256 / 256 * 60 = 820.04241943359375 / мин.
Это число нужно как можно более точно представить в виде 16 битного счетчика,
потому, что в часах 8-битный процессор и его надо жалеть и холить. :)
Для этой цели нужно, как мне подсказали использовать эти самые цепные дроби.
Написал небольшую .NET программку (в ссылке выше) и получилось такое:
0) 820 : 820 / 1 = 820 diff: 0.04241943359375
1) 23 : 18861 / 23 = 820.0434782608695652173913043 diff: -0.0010588272758152173913043
2) 1 : 19681 / 24 = 820.0416666666666666666666667 diff: 0.0007527669270833333333333
3) 1 : 38542 / 47 = 820.0425531914893617021276596 diff: -0.0001337578956117021276596
4) 2 : 96765 / 118 = 820.0423728813559322033898305 diff: 0.0000465522378177966101695
5) 1 : 135307 / 165 = 820.0424242424242424242424242 diff: -0.0000048088304924242424242
6) 6 : 908607 / 1108 = 820.0424187725631768953068592 diff: 0.0000006610305731046931408
7) 1 : 1043914 / 1273 = 820.0424194815396700706991359 diff: -0.0000000479459200706991359
8) 11 : 12391661 / 15111 = 820.0424194295546290781549864 diff: 0.0000000040391209218450136
9) 1 : 13435575 / 16384 = 820.04241943359375 diff: 0.00000000000000
Поэтому взял 3) 38542 / 47 = 820.04255319 diff: -0.000133
Это конечно хорошо, но вдруг в диапазоне 38542-65535 есть лучшее приближение?
Хотя точность 0.1 миллионная это 1 секунда за 116 дней - это неплохо
и вряд ли кварц стабильнее.
Но все же таки задача открыта - как без перебора найти наилучшую дробь,
числитель или знаменатель не превышает данное число?
Хотя перебрать несложно - нужно просто увеличивать знаменатель с 47 до 79 и найти
наименьшую погрешность...
Может кому-то нужна программка, которая считает цепные дроби, дарю бизвазмездна:
namespace MathTools
{
public class Frac
{
public long a, n1, n2;
}
using FracSeq = List;
using FracList = List;
public partial class FracForm : Form
{
private FracSeq Fractions;
private void ButtonCalculate_Click(object sender, EventArgs e)
{
try
{
textBoxOut.Text = "";
decimal val = decimal.Parse(textBoxInput.Text);
decimal v = val;
Fractions = new FracSeq();
FracList frac = new FracList();
int i = 0;
for (; ; )
{
long a = (long)v;
v = 1 / (v - (decimal)a);
frac.Insert(0, a);
// calculate whole fraction:
long n1 = 1, n2 = 0;
foreach (long f in frac)
{
long n = n1; n1 = n2; n2 = n; // flip
n1 += n2 * f;
}
Frac fr = new Frac() { a = a, n1 = n1, n2 = n2 };
Fractions.Add(fr);
decimal app = (decimal)n1 / (decimal)n2;
decimal diff = val - app;
textBoxOut.Text += $"{i})\t{a}\t: {n1} / {n2}\t= {app}\tdiff: {diff}\r\n";
if (diff == 0)
break;
++i;
}//for(;;)
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
}
} P.S. Кстати омереканские блюстители времени обновили сайт:
https://time.gov/
Стало веселее и наряднее. Прямо как бабский сарафан какой-то.
Празднек в каждую избу! :)