PhysUnitCalc: о литералах, унарных минусах и порядке действий

Nov 30, 2019 04:05

Что-то вожжа под хвост попала эту штуковину хоть немножко "причесать". И вспомнил о старой дилемме насчёт интерпретации знака "минус".

Напишем простейшее выражение:

-5

Этот знак "минус" можно интерпретировать по крайней мере тремя разными способами!

Можно сказать, что он относится непосредственно к числу, входит в "литерал". Т.е когда мы при синтаксическом разборе ожидаем встретить какую-то константу или переменную, то пусть в константе может содержаться минус.

Когда-то я так и делал, что позволяло специально не вводить унарную операцию - только бинарные трёх разных приоритетов (самый большой приоритет у возведения в степень ^, ниже у умножения и деления, самый низкий у сложения и вычитания). Но тогда выражение

-pi

станет "запрещённым".

Для этого тоже костыль можно подставить, но не надо - есть ещё одна проблема серьёзнее в таком подходе. А именно, выражение

-5^2

т.е "-52", однозначно воспринимается нами, как возведение 5 в квадрат, и взятие со знаком "минус". Поэтому нельзя минус относить к литералу - это сделает его самым приоритетным, и результатом такого выражения станет 25, без минуса!

Так что нам всё-таки нужна отдельная операция - "унарный минус". И её приоритет должен быть ниже, чем у возведения в степень!

Ровно так сейчас сделано в PhysUnitCalc.

Ну, почти. На самом деле, при делении выражения на слагаемые мы попросту допустили отсутствие самого первого слагаемого. Мы сначала приравниваем сумму к нулю, а затем прибавляем либо вычитаем каждое следующее слагаемое. Это позволяет не вводить дополнительной унарной операции, хотя я всё равно её ввёл. Одна проблема для моих "размерных величин" что я раз и навсегда решил, что нуль также является размерным, т.е прибавить к 5 метрам 0 секунд всё равно нельзя :) Поэтому тупо инициализировать нашу сумму нулём тоже не так-то просто. (правда, я мог отказаться от этого правила, когда попытался "протащить" размерные величины через решение системы линейных уравнений, уже точно не помню).

А вот дальше я допустил большую ошибку с присвоением размерности числу или выражению. По сути, я начал с того же - хотел сделать единицу измерения "частью числа", чтобы мы при синтаксическом разборе доходили до фрагмента "5 В" и воспринимали это как величину "пять вольт". Потом решил выделить отдельный "оператор присвоения размерности", что позволяет записывать что-то типа "(5 + 4,7) В", и оно в общем-то работает правильно.

Но приоритет такому оператору отдан наивысший, что казалось логичным - число и единица измерения, казалось бы, должны быть "неразрывными".

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

-20 °C

Температура минус двадцать по цельсию - кажется, что всё нормально. Не тут-то было. Если ввести такое выражение в PhysUnitCalc и нажать Enter, он выдаст:

-20 °C{-1}

А если потом попытаемся преобразовать в кельвины, выйдет так:

> -20 °C [K]
-293,15 К{-1}

Неплохо так, на 293 кельвина ниже абсолютного нуля!!!

Вся проблема, что мы решили радикально решить проблему перевода ТЕМПЕРАТУРЫ и РАЗНОСТИ ТЕМПЕРАТУР между разными единицами измерения, введя "множитель". Если мы указываем температуру, то множитель единица. Вычитаем одну из другой - множитель получается ноль, что означает - кельвины и цельсии становятся одним и тем же. Разница в 20 кельвинов равна разнице в 20 градусов цельсия. Но с тем же успехом можно сложить две температуры, и множитель станет равен двум. Затем поделить на два (взять среднее арифметическое) и он вернётся к единице.

Исходя из этой логики, унарный минус, применённый к ТЕМПЕРАТУРЕ, должен обратить её множитель, что мы здесь и наблюдаем. Чтобы сейчас в PhysUnitCalc записать -20 °С, нужно величину взять в скобки:

(-20) °C

Теперь преобразование в кельвины пройдёт нормально:

> (-20) °C [K]
253,15 К

Ровно то же самое с децибелами. Напишем:

-20 dBV

это должно быть минус двадцать децибел-вольт, то есть, 0,1 В. Жмём Enter:

> -20 dBV
Лог. единицы измерения допустимы только для положительных действительных значений

Произошло то же самое: сначала образовалась величина 20 дБВ, а потом уже её попытались обратить. Я когда-то решил, что у нас должна быть "инвариантность к смене единицы измерения", т.е выражение должно означать одно и то же, без разницы, в чём мы выразили величины. Поэтому знак минус в любом случае означает взятие противоположного напряжения. Если 20 дБВ = 10 В, то здесь получается -10 вольт, а они уже в децибел-вольтах не выражаются. Комплексный логарифм я здесь ещё не применял, хотя это было бы правильно. Что это за инвариантность такая, если подставив куда-нибудь децибел-вольты вместо нормальных вольт, мы не сможем выражение посчитать!

Опять же, скобки проблему решают:

> (-20) dBV [V]
0,1 В

Но это некрасиво!

Исходя из этого, приоритет операции присвоения размерности должен стать НИЖЕ, чем унарного минуса. Тогда приведённые выше примеры будут восприняты программой также, как воспринимаются человеком.

Ещё надо посмотреть, как между собой "дружат" присвоение размерности и возведение в степень. Если мы напишем такое выражение:

5^2 m

то нынешний PhysUnitCalc решит, что мы хотим возвести число пять в степень "два метра", на что будет выдана ошибка - "показатель степени должен быть безразмерным".

Если выставить правильный порядок операций, ответ будет: 25 метров. Особенно это логично будет, если я-таки напишу PhysTeXCalc, который автоматом изобразит выражение так:

52 m.

Тогда очевидно, что у возведения в степень приоритет и должен быть выше!

странные девайсы, математика, программки, physunitcalc

Previous post Next post
Up