Дело не в поговорить.
Интересно когда код улучшают, исправляют, вы дважды выложили не рабочий код, Зачем?
Тема ПЛК (среда CoDeSys V2.3)ПЛК1хх при чём тут Полигон?
Вид для печати
Дело не в поговорить.Цитата:
Первый вариант я достал из загашника, он был написан мной лет пять назад для БЕРЕМИЗ, как есть в ПОЛИГОНЕ он не работал, ПОЛИГОН не понимает неявного преобразования типов, поэтому появился LINT_TO_INT. второго кодесис у меня нет, я уже писал. Я понял, что Вам скучно, просто хочется поговорить)
Интересно когда код улучшают, исправляют, вы дважды выложили не рабочий код, Зачем?
Тема ПЛК (среда CoDeSys V2.3)ПЛК1хх при чём тут Полигон?
Думаю, что я последний раз тут что-то выложил) сейчас есть нейросети, на форуме можно туда ссылку сделать. там дадут любой ответ на любой вопрос. к тому же нейросеть не станет хамить, цепляться, и пытаться самоутверждаться за счет других))
Чат GPT5 четыре раза пытался исправить код и каждый раз код не работал на пределах от -0.99999 до -0.00001 и от 0.00001 до 0.99999, при чём именно это я и просил исправить, потом кончилось время.
Тупые ИИ в действии.
Используйте рабочий код, ссылка выше, это всё о чём хотел сказать ТС, только он не понял).
что конкретно не работало? Вложение 88195 мой ИИ утверждает что все совпадает из этого кодаЦитата:
Чат GPT5 четыре раза пытался исправить код и каждый раз код не работал на пределах от -0.99999 до -0.00001 и от 0.00001 до 0.99999, при чём именно это я и просил исправить, потом кончилось время.
Тупые ИИ в действии.
Используйте рабочий код, ссылка выше, это всё о чём хотел сказать ТС, только он не понял).
Скрытый текст:
Код:FUNCTION_BLOCK FB_RealToWords_IEEE754
VAR_INPUT
InputReal : REAL;
END_VAR
VAR_OUTPUT
WordHigh : WORD; // Биты 31-16
WordLow : WORD; // Биты 15-0
StatusCode : INT; // 0: Normal, 1: Zero, 2: Infinity, 3: NaN
END_VAR
VAR
Sign : BOOL;
AbsValue : REAL;
Exponent : INT;
Mantissa : DINT;
BiasedExp : BYTE;
SignBit : DINT;
TempDword : DINT;
i : INT;
Fraction : REAL;
ScaledMant : REAL;
END_VAR
// ============================================================================
// ШАГ 1: Обработка особых случаев (до математических операций)
// ============================================================================
// Проверка на NaN (NaN != NaN по стандарту IEEE 754)
IF (InputReal <> InputReal) THEN
// NaN: Exponent = 255 (16#FF), Mantissa != 0
SignBit := 0; // Для NaN знак обычно игнорируем
BiasedExp := 255;
Mantissa := 16#00400000; // Quiet NaN (старший бит мантиссы = 1)
StatusCode := 3;
// Сборка DWORD
TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
WordLow := DWORD_TO_WORD(TempDword);
RETURN;
END_IF;
// Проверка на бесконечность (через сравнение с максимальным REAL)
// Примечание: в некоторых реализациях потребуется флаг от переполнения
IF (InputReal > 3.40282347E+38) OR (InputReal < -3.40282347E+38) THEN
// Infinity: Exponent = 255, Mantissa = 0
SignBit := 1;
BiasedExp := 255;
Mantissa := 0;
StatusCode := 2;
TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
WordLow := DWORD_TO_WORD(TempDword);
RETURN;
END_IF;
// ============================================================================
// ШАГ 2: Извлечение знака
// ============================================================================
IF InputReal < 0.0 THEN
Sign := TRUE;
SignBit := 1;
AbsValue := -InputReal; // Сохраняем абсолютное значение
ELSIF InputReal > 0.0 THEN
Sign := FALSE;
SignBit := 0;
AbsValue := InputReal;
ELSE
// Случай нуля (+0.0 или -0.0)
// Для сохранения знака -0.0 проверяем 1.0/InputReal
IF (1.0 / InputReal) < 0.0 THEN
Sign := TRUE;
SignBit := 1;
ELSE
Sign := FALSE;
SignBit := 0;
END_IF;
// Zero: Exponent = 0, Mantissa = 0
BiasedExp := 0;
Mantissa := 0;
StatusCode := 1;
TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
WordLow := DWORD_TO_WORD(TempDword);
RETURN;
END_IF;
// ============================================================================
// ШАГ 3: Нормализация числа (находим экспоненту без LOG)
// ============================================================================
Exponent := 0;
Fraction := AbsValue;
// Если число >= 2.0, делим на 2 пока не попадём в диапазон [1.0, 2.0)
WHILE Fraction >= 2.0 DO
Fraction := Fraction * 0.5; // Деление на 2
Exponent := Exponent + 1;
END_WHILE;
// Если число < 1.0, умножаем на 2 пока не попадём в диапазон [1.0, 2.0)
WHILE Fraction < 1.0 DO
Fraction := Fraction * 2.0;
Exponent := Exponent - 1;
END_WHILE;
// Теперь Fraction в диапазоне [1.0, 2.0), Exponent - порядок числа
// ============================================================================
// ШАГ 4: Вычисление смещённой экспоненты (Bias = 127)
// ============================================================================
BiasedExp := BYTE_OF(Exponent + 127);
// Проверка на переполнение/исчезновение экспоненты
IF BiasedExp >= 255 THEN
// Переполнение -> Infinity
BiasedExp := 255;
Mantissa := 0;
StatusCode := 2;
TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
WordLow := DWORD_TO_WORD(TempDword);
RETURN;
ELSIF BiasedExp <= 0 THEN
// Исчезновение -> Denormal или Zero
BiasedExp := 0;
// Для денормализованных чисел нужна дополнительная обработка
Mantissa := 0;
StatusCode := 1;
TempDword := SHL(SignBit, 31) OR SHL(BiasedExp, 23) OR Mantissa;
WordHigh := DWORD_TO_WORD(SHR(TempDword, 16));
WordLow := DWORD_TO_WORD(TempDword);
RETURN;
END_IF;
// ============================================================================
// ШАГ 5: Извлечение мантиссы (23 бита)
// ============================================================================
// Fraction сейчас в диапазоне [1.0, 2.0)
// Убираем ведущую 1 (она неявная в IEEE 754)
Fraction := Fraction - 1.0; // Теперь [0.0, 1.0)
// Преобразуем дробную часть в 23-битную мантиссу
// Умножаем на 2^23 = 8388608
ScaledMant := Fraction * 8388608.0;
Mantissa := DINT_OF(ScaledMant + 0.5); // Округление
// Ограничиваем мантиссу 23 битами (маска 16#007FFFFF)
Mantissa := Mantissa AND 16#007FFFFF;
// ============================================================================
// ШАГ 6: Сборка 32-битного представления
// ============================================================================
// Формат: [Sign:1][Exponent:8][Mantissa:23]
// Бит 31: Знак
// Биты 30-23: Экспонента
// Биты 22-0: Мантисса
TempDword := 0;
// Добавляем бит знака (бит 31)
IF SignBit = 1 THEN
TempDword := TempDword OR 16#80000000;
END_IF;
// Добавляем экспоненту (биты 30-23)
TempDword := TempDword OR SHL(DINT_OF(BiasedExp), 23);
// Добавляем мантиссу (биты 22-0)
TempDword := TempDword OR Mantissa;
// ============================================================================
// ШАГ 7: Разделение на два WORD
// ============================================================================
WordHigh := DWORD_TO_WORD(SHR(TempDword, 16)); // Старшие 16 бит
WordLow := DWORD_TO_WORD(TempDword); // Младшие 16 бит
StatusCode := 0; // Normal
END_FUNCTION_BLOCK
Вот код для CDS 2.3, который просил исправить для работы в диапазоне от -0.99999 до -0.00001 и от 0.00001 до 0.99999Цитата:
Он же не работает в Лоджике, с исправлениями конечно.
Скрытый текст:Код:FUNCTION_BLOCK REAL_TO_WW
VAR_INPUT
rIn : REAL; (* Входное число *)
END_VAR
VAR_OUTPUT
wLow : WORD; (* Слово 2 для Modbus *)
wHigh : WORD; (* Слово 1 для Modbus *)
END_VAR
VAR
(* Промежуточные переменные *)
rAbs : REAL;
iSign : DWORD;
iExp : DINT;
rMantissa : REAL;
iMantissa : DWORD;
dwResult : DWORD; (* Итоговое 32-битное число *)
END_VAR
(* 1. Обработка нуля — особый случай в IEEE-754 *)
IF rIn = 0.0 THEN
dwResult := 0;
ELSE
(* 2. Определяем знак (бит 31) *)
IF rIn < 0.0 THEN
iSign := 16#80000000;
rAbs := ABS(rIn);
ELSE
iSign := 16#0;
rAbs := rIn;
END_IF
(* 3. Вычисляем экспоненту (биты 30..23) *)
(* Экспонента — это целая часть логарифма по основанию 10 *)
iExp := TRUNC(LOG(rAbs) / 0.30103); (* 0.30103 ? LOG(2) *)
(* 4. Вычисляем мантиссу (биты 22..0) *)
(* Убираем из числа степень двойки, оставляя значение [1.0 ... 2.0) *)
rMantissa := rAbs / EXPT(2.0, iExp);
(* В IEEE-754 первая единица мантиссы не записывается (скрытый бит) *)
(* Оставшуюся дробную часть растягиваем на 23 бита (2^23 = 8388608) *)
iMantissa := REAL_TO_DWORD((rMantissa - 1.0) * 8388608.0);
(* 5. Сборка итогового DWORD *)
(* Смещаем экспоненту на 127 (bias) и сдвигаем на 23 позиции влево *)
dwResult := iSign OR SHL(DINT_TO_DWORD(iExp + 127), 23) OR iMantissa;
END_IF
(* 6. Разрезаем на два WORD для Modbus *)
wHigh := DWORD_TO_WORD(SHR(dwResult, 16));
wLow := DWORD_TO_WORD(dwResult AND 16#FFFF);
за свой вопрос к ИИ я сразу оговорил не использовать экспоненты и степени, а сейчас еще и про ограничения ОЛ и вроде считает, за исключением инфинитиЦитата:
код для ОЛ:Код:function_block FB_RealToWords_IEEE754
VAR_INPUT
InputReal : REAL;
END_VAR
VAR_OUTPUT
WordHigh : udint; // Старшие 16 бит (биты 31–16)
WordLow : udint; // Младшие 16 бит (биты 15–0)
StatusCode : udint; // 0: Normal, 1: Zero, 2: Infinity, 3: NaN
END_VAR
VAR
Sign : BOOL;
AbsValue : REAL;
Exponent : udint;
Mantissa : udint;
BiasedExp : udint;
SignBit : udint;
TempDword : udint;
i : udint;
buff_val : udint;
Fraction : REAL;
ScaledMant : REAL;
END_VAR
// ============================================================================
// ШАГ 1: Обработка особых случаев (до математических операций)
// ============================================================================
// Проверка на NaN (NaN != NaN по стандарту IEEE 754)
IF (InputReal <> InputReal) THEN
// NaN: Exponent = 255, Mantissa != 0
SignBit := 0;
BiasedExp := 255;
Mantissa := 4194304; // Quiet NaN
StatusCode := 3;
// Сборка UDINT
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
END_IF;
// Проверка на бесконечность
IF (InputReal > 3.40282347E+38) OR (InputReal < -3.40282347E+38) THEN
// Infinity: Exponent = 255, Mantissa = 0
IF InputReal < 0.0 THEN
SignBit := 1;
ELSE
SignBit := 0;
END_IF;
BiasedExp := 255;
Mantissa := 0;
StatusCode := 2;
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
END_IF;
// ============================================================================
// ШАГ 2: Извлечение знака
// ============================================================================
IF InputReal < 0.0 THEN
Sign := TRUE;
SignBit := 1;
AbsValue := -InputReal;
ELSIF InputReal > 0.0 THEN
Sign := FALSE;
SignBit := 0;
AbsValue := InputReal;
ELSE
// Случай нуля
Sign := FALSE;
SignBit := 0;
BiasedExp := 0;
Mantissa := 0;
StatusCode := 1;
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
END_IF;
// ============================================================================
// ШАГ 3: Нормализация числа
// ============================================================================
Exponent := 0;
Fraction := AbsValue;
WHILE Fraction >= 2.0 DO
Fraction := Fraction * 0.5; // Деление на 2
Exponent := Exponent + 1;
END_WHILE;
WHILE Fraction < 1.0 DO
Fraction := Fraction * 2.0;
Exponent := Exponent - 1;
END_WHILE;
// ============================================================================
// ШАГ 4: Вычисление смещённой экспоненты (Bias = 127)
// ============================================================================
BiasedExp := Exponent + 127;
IF BiasedExp >= 255 THEN
// Переполнение -> Infinity
BiasedExp := 255;
Mantissa := 0;
StatusCode := 2;
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
ELSIF BiasedExp <= 0 THEN
// Исчезновение -> Zero
BiasedExp := 0;
Mantissa := 0;
StatusCode := 1;
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
END_IF;
// ============================================================================
// ШАГ 5: Извлечение мантиссы (23 бита)
// ============================================================================
Fraction := Fraction - 1.0; // Убираем ведущую 1
ScaledMant := Fraction * 8388608.0; // 2^23 = 8388608
Mantissa := real_to_udint(ScaledMant + 0.5); // Округление
// Ограничиваем мантиссу 23 битами
Mantissa := Mantissa MOD 8388607;
// ============================================================================
// ШАГ 6: Сборка 32‑битного представления
// ============================================================================
TempDword := 0;
// Добавляем бит знака (бит 31)
IF SignBit = 1 THEN
TempDword := TempDword + 2147483648;
END_IF;
// Добавляем экспоненту (биты 30–23)
TempDword := TempDword + shl(BiasedExp, 23);
// Добавляем мантиссу (биты 22–0)
TempDword := TempDword + Mantissa;
// ============================================================================
// ШАГ 7: Разделение на два 16‑битных блока
// ============================================================================
buff_val := shr(TempDword, 16);
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
StatusCode := 0; // Normal
end_function_block

