Цитата Сообщение от kondor3000 Посмотреть сообщение
Вот код для CDS 2.3, который просил исправить для работы в диапазоне от -0.99999 до -0.00001 и от 0.00001 до 0.99999
Он же не работает в Лоджике, с исправлениями конечно.
за свой вопрос к ИИ я сразу оговорил не использовать экспоненты и степени, а сейчас еще и про ограничения ОЛ и вроде считает, за исключением инфинити
код для ОЛ:
Код:
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