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

 
 
> Преобразовать число с плавающей точкой в простую дробь., Нужен оптимальный алгоритм пересчета
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
 
Start new topic
Ответов
_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

Сообщений в этой теме
- M_Andrey   Преобразовать число с плавающей точкой в простую дробь.   Jun 8 2016, 12:56
- - Tanya   Цитата(M_Andrey @ Jun 8 2016, 15:56) Вста...   Jun 8 2016, 15:05
|- - M_Andrey   Цитата(Tanya @ Jun 8 2016, 18:05) https:/...   Jun 8 2016, 16:19
|- - Maverick   Цитата(M_Andrey @ Jun 8 2016, 19:19) Не п...   Jun 9 2016, 05:21
|- - M_Andrey   Цитата(M_Andrey @ Jun 8 2016, 19:19) PS. ...   Jun 9 2016, 07:29
- - jcxz   Цитата(M_Andrey @ Jun 8 2016, 18:56) Вста...   Jun 9 2016, 08:25
|- - M_Andrey   Цитата(jcxz @ Jun 9 2016, 11:25) Теперь р...   Jun 9 2016, 09:04
||- - jcxz   Цитата(M_Andrey @ Jun 9 2016, 15:04) А ка...   Jun 9 2016, 09:52
|- - XVR   Цитата(jcxz @ Jun 9 2016, 11:25) Теперь р...   Jun 10 2016, 08:47
|- - jcxz   Цитата(XVR @ Jun 10 2016, 14:47) Это ровн...   Jun 10 2016, 08:52
- - XVR   Его не устроил результат, и он хочет дроби поменьш...   Jun 10 2016, 09:05


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

 


RSS Текстовая версия Сейчас: 29th July 2025 - 15:25
Рейтинг@Mail.ru


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