27 мая

LabVIEW NXG — простые типы данных и приведение типов

LabVIEW

Это третья статья из цикла о LabVIEW NXG, в которой мы рассмотрим простые типы данных и несложные преобразования между ними.



Система типов LabVIEW весьма похожа на "классические" языки программирования. В данной статье мы рассмотрим базовые типы — численные, булевские и строки (хотя формально строки не относятся к простым скалярным типам).


Самый простой способ понять систему типов — сделать небольшой инструмент с контролами и индикаторами разных типов:



и соединим их на диаграмме вот так:



Чтобы подчеркнуть различие контролов и индикаторов, я добавил к именам " In" и " Out". Это общепринятая практика в LabVIEW, так как подчёркивает принцип потоков данных, когда контролы и индикаторы используются как терминалы подприборов (о которых мы ещё поговорим).


В случае с численными индикаторами мы можем один из четырнадцати доступных нам типов — знаковые и беззнаковые целые, занимающие 8, 16, 32 или 64 бита, числа с плавающей точкой одинарной или двойной точности (они будут занимать 4 или 8 байт), комплексные числа также одинарной или двойной точности и числа с фиксированной точностью — также простые или комплексные. Тип переключается вот здесь в контекстном меню:



Или вот здесь в панели свойств:



При первом присоединении числового индикатора к проводнику он автоматически меняет тип на тип проводника (а тип проводника совпадает с типом контрола, к которому он подключён). Что произойдёт, если тип индикатора будет отличаться от типа проводника? Вот смотрите:



У нас "загорелись" красные точки (которые называются Coercion Dots), которые говорят нам о том, что в местах подсоединения происходит неявное преобразование типа.


В случае если мы преобразуем SGL в DBL или, скажем, U8 в I32, то ничего страшного не произойдёт, однако преобразование в обратном направлении DBL->SGL, либо DBL->I32 или I32->U8 может привести к потере точности, либо округлениям:



Хорошим "тоном" программирования на LabVIEW считается полное отсутствие Coercion Dots на диаграмме, тем более что каждая такая точка будет добавлять вам предупреждение:



Как поступить в том случае, если вам действительно нужны явные преобразования типов? Для этого есть соответствующие примитивы преобразования, которые находятся вот здесь в палитре Data Types->Numeric->Conversion:



А в контекстном меню эти функции находятся вот здесь:



Вставив соответствующий элемент в проводник вы явно укажете как вы хотите преобразовать данные и это уберёт Coercion Dot, равно как и предупреждение.



Неявное преобразование типов также распространяется и на математические примитивы, например, если вы хотите прибавить целое к числу с плавающей точкой, то вначале целое будет приведено к типу DBL, и лишь затем будет выполнено сложение:



Кстати, вы можете использовать несколько терминалов при использовании некоторых арифметических операций, для этого надо просто потянуть вниз или вверх вот здесь (в классической LabVIEW приходилось менять этот примитив на Compound Arithmetic):



По сравнению с классическими текстовыми языками у LabVIEW есть некоторые отличия. Допустим, вы хотите поделить два целых:


double res;
res = 5/3;
Console.WriteLine(res);

результат будет "1".


А в LabVIEW будет выполнено приведение типов, и результат будет 1,66 (1,66666666666667 если быть дотошным):



Следует отметить, что LabVIEW предоставляет вам немножко больше свободы, чем, скажем, C# (степень "типизированности" у всех языков разная).


Вот, к примеру, мы хотим сложить два байта:



Как видите, здесь не возникает никаких предупреждений и никакого приведения. Самом собой, мы получим переполнение, но мы получаем именно то, что хотим:



В то время как в C# такое даже компилятор не пропустит (ибо операция сложения для байтов не определена, они будут неявно перобразованы в int, затем сложены, а неявное преобразование обратно в байт невозможно:


        static void Main(string[] args)
        {
        byte x_U8 = 200, y_U8 = 200, res_U8;

        res_U8 = x_U8 + y_U8;

            Console.WriteLine(res_U8);
        }

И вам придётся сделать вот так:


        res_U8 = (byte)(x_U8 + y_U8);

Обратите внимание, что подобное приведение можно сделать и в LabVIEW, явно указав тип терминалов операции сложения, при этом LabVIEW укажет нам, на то, что мы вручную изменили тип синей точкой на выходе (при этом предупреждения не будет):



Но лучше всего при подобных перобразованиях делать вот так, причём можно использовать комментарии на проводниках, чтобы подчеркнуть тип данных:



Ещё одна особенность LabVIEW (которая присутствует и во многих "традиционных" языках) — наличие бесконечности и неопределённости.


Прежде чем продолжить с LabVIEW мне хотелось бы расчехлить C# и бросить камушек в огород компании Microsoft, ибо вот такой несложный код:


class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(5.0/0.0);
    }
}

выдаёт мне "8". Но, разумеется, это не "восемь", это "Infinity", просто надо голову повернуть набок. Ирония в том, что это .NET Core — продукт компании Микрософт, запускаемый в консоли Микрософт и под управлением операционной системы Микрософт (и да, я только что поставил новый, "с иголочки" Windows 10 версии 2004). В принципе исходники открыты, и, вероятно, убив некоторое количество времени, я могу разобраться в чём там дело, но если вы считаете, что это нормально, бросьте этот камушек в меня обратно.


Ну, как бы то ни было, давайте поделим на нуль в LabVIEW:



Результат деления на нуль — бесконечность. Минус нуль у нас тоже есть и получится минус бесконечность:



Ну а если делить нуль на нуль, то будет NaN (Not a Number):



Мы можем проанализировать если мы получаем NaN при помощи примитива Not a Number? из палитры сравнения:



Результат этого кода — истина.


Чуть сложнее с целыми.


В С# данный код компилятор не пропустит:


static void Main(string[] args)
{
    Console.WriteLine(5/0);
}

но я могу схитрить...


static void Main(string[] args)
{
    int zero = 0; 
    Console.WriteLine(5/zero);
}

… и получирть исключение System.DivideByZeroException, однако в LabVIEW вы этого не дождётесь — здесь вы получите нуль, так что будьте аккуратны.



Преобразования между числами и строками


Напрямую (неявным) образом выполнить такое преобразование нельзя:



Для этого в палитре Conversions предусмотрены соответствующие функции:



Применяется вот так:



В обратную сторону преобразование выполняется аналогичным образом, с той лишь разницей, что функции преобразования находятся в палитре работы со строками:



Применяется вот так:



Ещё один маленький и, возможно, неочевидный нюанс со строками для тех кто привык делать вот так:


    static void Main(string[] args)
    {
    string hello = "Hello, ";
    string habr = "Habr!";

        Console.WriteLine(hello + habr);
    }

В LabVIEW "один в один" не получится, для этого есть отдельная функция объединения строк:



Базовые операции с булевским типом


Ровно тоже самое и с булевским типом. Вы не можете соединить численный проводник с булевским терминалом напрямую и наоборот, но вы можете использовать функции сравнения и примитив Boolean to Integer для обратного преобразования:



Особенности сравнения чисел с плавающей точкой справедливы и для LabVIEW. Данный код вернёт False:



Машинный эпсилон находится в разделе констант, вот здесь:



Type Cast


Ну и напоследок хотелось бы затронуть тему преобразования "Type Cast", которая часто вводит в заблуждение. Я имею ввиду вот эту функцию:



У неё есть дополнительный терминал "Type", который задаёт выходной тип. Ключевой момент здесь в словах "by flattening it and unflattening". Самый ближайший аналог "сериализация/десериализация".


Предположим, для простоты я возьму четырёхбайтный тип SGL и преобразую его в I32:



Чему будет равен output? Правильный ответ "1040187392". Почему такое странное число?


Давайте переключим индикатор в шестнадцатиричное представление и всё станет понятнее:



Это 0x3E000000. Здесь происходит следующее — четыре байта числа с плавающей точкой реинтерпретируются как четырёхбайтное целое. Я намеренно взял число 0,125, потому что если вы посмотрите на представление 0,125 согласно IEEE754, то увидите, что там всего пять битов мантиссы установлено — это и даёт нам значение 3Е в старшем байте.


После трёх статей мы должны достаточно уверенно работать с тремя типами данных:



Если есть какие-либо вопросы по изложенному материалу — спрашивайте в комментариях, а в следующей статье мы рассмотрим массивы.

Теги:labview
Хабы: LabVIEW
+6
1,4k 8
Комментировать
Похожие публикации
SEO-специалист
7 декабря 202064 900 ₽Нетология
Факультет интернент-маркетинга
7 декабря 2020210 000 ₽GeekBrains
Профессия iOS-разработчик
7 декабря 202090 000 ₽SkillFactory
Курс по аналитике данных
7 декабря 202064 200 ₽SkillFactory
iOS-разработчик с нуля
7 декабря 202070 740 ₽Нетология
Лучшие публикации за сутки