реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Преобразовать число с плавающей точкой в простую дробь., Нужен оптимальный алгоритм пересчета
M_Andrey
сообщение Jun 8 2016, 12:56
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 158
Регистрация: 15-10-07
Из: Й-Ола
Пользователь №: 31 376



Встала задача преобразовать число single/double в простую дробь.
Классическое правило:
1.2345 = 12345 / 10000
Находим наибольший общий делитель НОД(12345,10000)=5 и сокращаем дробь:
12345 / 10000 = 2469 / 2000
Еще нашел способ:
CODE
d = 0.12345; // Исходная дробь, может быть любой
a0 = 0; a1 = 1; b0 = 1; b1 = 0;
while(не_достигнута_нужная точность)
{
N = Floor(d);
a = N * a1 + a0;
b = N * b1 + b0;
printf("%d / %d = %f\n", a, b, a/b);
a0 = a1; a1 = a; b0 = b1; b1 = b;
d = 1/(d - N);
}

Первый способ дает неоптимальные числа (слишком большие) при той-же точности, у второго в алгоритме есть дыры типа деления на ноль. Может кто-то уже проходил этот путь? Что посоветуете?
Go to the top of the page
 
+Quote Post
_pv
сообщение Jun 8 2016, 13:46
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



для чего, если не секрет?

1.2345 = 1.2345 / 1 = 2.469 / 2 = 3.7035 / 3 = ... = 457.9995/371 ~ 458/371 = ... = 2469 / 2000
правда очень не быстро, зато найдёт минимальное число с любой заданной точностью.
Go to the top of the page
 
+Quote Post
M_Andrey
сообщение Jun 8 2016, 13:57
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 158
Регистрация: 15-10-07
Из: Й-Ола
Пользователь №: 31 376



Цитата(_pv @ Jun 8 2016, 16:46) *
для чего, если не секрет?

Нужно вводить коэффициент редуктора двигателя в частотник из верхнего софта.
Прикрепленное изображение
Go to the top of the page
 
+Quote Post
Maverick
сообщение Jun 8 2016, 14:00
Сообщение #4


я только учусь...
******

Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Цитата(M_Andrey @ Jun 8 2016, 16:57) *
Нужно вводить коэффициент редуктора двигателя в частотник из верхнего софта.

посмотрите
MATLAB:
Код
rat(pi)
            ans = 3 + 1/(7 + 1/(16))
            rat(pi, 1e-12)
            ans = 3 + 1/(7 + 1/(16 + 1/(-294 + 1/(3 + 1/(-4 + 1/(5))))))
            [n,d]=rat(pi);
            [n d]
            ans =   355     113
            [n, d]=rat(pi, 1e-12);
            [n d]
            ans =    5419351    1725033
            s = rats(pi)
            s = 355/113
            s = rats(pi, 26)
            s = 5419351/1725033
Причина редактирования: Избыточное цитирование


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
M_Andrey
сообщение Jun 8 2016, 14:12
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 158
Регистрация: 15-10-07
Из: Й-Ола
Пользователь №: 31 376



Если-бы мне надо было сделать это один раз, то я бы на калькуляторе посчитал и ввел один раз. Но эти коэффициенты наладчики будут вводить на объектах из верхнего софта (HMI SCADA), программа ПЛК получает число (double), пересчитывает в числитель и знаменатель, и передает их частотнику.
Go to the top of the page
 
+Quote Post
_pv
сообщение Jun 8 2016, 14:52
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(M_Andrey @ Jun 8 2016, 21:12) *
эти коэффициенты наладчики будут вводить на объектах из верхнего софта (HMI SCADA), программа ПЛК получает число (double), пересчитывает в числитель и знаменатель, и передает их частотнику.

ну раз наладчики вводят, то перебор всех 30000 значений для поиска оптимального могут и подождать лишнюю милисекунду.

double n = 1.2345;
double maxErr = 0.0001;

int denom = 1;
double err = n;
for(int i = 1; i <= 30000; i++){
double e = abs((double)((int)(n * i + 0.5)) / i - n );
if (e < err){ err = e; denom = i;}
if (e < maxErr) break;
}

получившаяся дробь: (n * denom + 0.5) / denom
Go to the top of the page
 
+Quote Post
Tanya
сообщение Jun 8 2016, 15:05
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 8 752
Регистрация: 6-01-06
Пользователь №: 12 883



Цитата(M_Andrey @ Jun 8 2016, 15:56) *
Встала задача преобразовать число single/double в простую дробь.
Что посоветуете?


https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%...%BE%D0%B1%D1%8C
Go to the top of the page
 
+Quote Post
M_Andrey
сообщение Jun 8 2016, 16:19
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 158
Регистрация: 15-10-07
Из: Й-Ола
Пользователь №: 31 376



Цитата(Tanya @ Jun 8 2016, 18:05) *

Не пойму как непрерывную дробь применить в моем случае.
PS. А вот "подходящая дробь" мой случай sm.gif Спасибо.
Go to the top of the page
 
+Quote Post
Maverick
сообщение Jun 9 2016, 05:21
Сообщение #9


я только учусь...
******

Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Цитата(M_Andrey @ Jun 8 2016, 19:19) *
Не пойму как непрерывную дробь применить в моем случае.
PS. А вот "подходящая дробь" мой случай sm.gif Спасибо.

посмотрите там алгоримтм и программа правда на PHP


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
M_Andrey
сообщение Jun 9 2016, 07:29
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 158
Регистрация: 15-10-07
Из: Й-Ола
Пользователь №: 31 376



Цитата(M_Andrey @ Jun 8 2016, 19:19) *
PS. А вот "подходящая дробь" мой случай sm.gif Спасибо.

Оказалось что второй способ в моем первом посте и есть реализация "подходящей дроби".
Вот только беда в том что постоянное деление (1/х) в каждой итеррации приводит к погрешности при вычислении даже конечной дроби.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2016, 08:25
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(M_Andrey @ Jun 8 2016, 18:56) *
Встала задача преобразовать число single/double в простую дробь.
Классическое правило:
1.2345 = 12345 / 10000
...
Может кто-то уже проходил этот путь? Что посоветуете?

Теперь разложите числитель и знаменатель на простые сомножители и сократите общую часть их.
Получите числитель и знаменатель в виде: 2^K1 * 3^K2 * 5^K3 * 7^K4... (где ^ - возведение в степень). Выберите минимальную степень из каждой пары Kn и поделите на неё.
Go to the top of the page
 
+Quote Post
M_Andrey
сообщение Jun 9 2016, 09:04
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 158
Регистрация: 15-10-07
Из: Й-Ола
Пользователь №: 31 376



Цитата(jcxz @ Jun 9 2016, 11:25) *
Теперь разложите числитель и знаменатель на простые сомножители и сократите общую часть их.
Получите числитель и знаменатель в виде: 2^K1 * 3^K2 * 5^K3 * 7^K4... (где ^ - возведение в степень). Выберите минимальную степень из каждой пары Kn и поделите на неё.

А как их искать - перебором? Мне нужен машинный алгоритм.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2016, 09:52
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(M_Andrey @ Jun 9 2016, 15:04) *
А как их искать - перебором? Мне нужен машинный алгоритм.

Гуглите "решето Сундарама". Быстрый алгоритм поиска всех простых чисел не превышающих некоторого N.
Далее, если математику в школе учили, находите квадратный корень от числа, которое надо разложить на множители, и Сундараму задаёте значение корня в качестве предела N.
Go to the top of the page
 
+Quote Post
XVR
сообщение Jun 10 2016, 08:47
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(jcxz @ Jun 9 2016, 11:25) *
Теперь разложите числитель и знаменатель на простые сомножители и сократите общую часть их.
Это ровно то, что ТС сделал и описал в самом первом сообщении темы.

Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 10 2016, 08:52
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(XVR @ Jun 10 2016, 14:47) *
Это ровно то, что ТС сделал и описал в самом первом сообщении темы.

Если он уже это сделал, то больше делать нечего, зачем бы тогда он спрашивал? Вы почитайте заголовок топика.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 03:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.02898 секунд с 7
ELECTRONIX ©2004-2016