Официальная возможность получить лицензионный софт бесплатно.
Giveaway of the Day
Это не реклама!

Щелкните для получения прогноза по Биробиджану


Показаны сообщения с ярлыком вычисления. Показать все сообщения
Показаны сообщения с ярлыком вычисления. Показать все сообщения

понедельник, 16 марта 2020 г.

Bash: разница в днях между двумя датами

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

echo $(( ( $(date +%s -d 4/13/2020 ) - $(date +%s -d 3/23/2020 ) )/86400 ))

Функция вычислений $(( выражение ))
Вывод команды $( команда )
Арифметическое операторы и скобки (-/)
Перевести дату, заданную параметром -d в формат UNIX-date (число секунд с начала эры) +%s
Начальная дата в формате mm/dd/yyyy 4/13/2020
Конечная дата в формате mm/dd/yyyy 3/23/2020
Разницу между датами делим на число секунд в сутках 86400

Есть и другие способы такой арифметики, но именно этот первым пришел в голову. Данная команда выдает результат "21", то есть, между 13 апреля 2020 года и 23 марта 2020 года 21 день

По арифметике с временами у меня есть более ранний пост.

пятница, 15 марта 2019 г.

bash: разница между двумя моментами времени

Есть у нас хитрая система учета рабочего времени, которая требует указывать продолжительность выполненных работ исключительно в минутах. Например, с 8:45 до 13:30 я был на выезде. Вопрос: сколько минут я должен записать?

Не, оно, конечно, несложно - "без 15 минут 5 часов", то есть, 4 часа 45 минут или 285 минут.
Но в гробу я видал заниматься временнОй арифметикой в уме - у меня есть и более интересные занятия. Поэтому написал небольшой не оптимизированный скрипт без наворотов, который чисто средствами баша считает разницу в минутах (и не только) между двумя моментами времени в пределах одних суток. Допиливать его под переход суток и т.п. мне лень, допилю, когда и если понадобится.

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

#!/bin/bash
<
<<Descriptions
 timediff - разница между двумя временами в пределах суток
 $1 - начальное время
 $2 - конечное время

 Формат параметров:
 ч:м[:с]
 ведущие нули не обязательны, но если нужно указать только минуты, то ноль часов указывать обязательно:
 :12:34 - неправильно
 0:12:34 - правильно

 Проверки на допустимость параметров не делаются, поэтому в случае чего вываливается с ошибкой "смените пользователя"

Descriptions

# с учетом возможной переделки, используем переменные для времен
# пока что $TimeX и $n - одно и то же, но в будущем это может измениться
TimeS=$1
TimeF=$2

# TimeStamp Start/Finish
TSS=$( date +%s -d $TimeS )
TSF=$( date +%s -d $TimeF )

# Разница в секундах, целых минутах, целых часах
DiffS=$(( $TSF-$TSS ))
DiffM=$(( $DiffS/60 ))
DiffH=$(( $DiffM/60 ))
# Сколько секунд сверх целых минут и минут сверх целых часов
ExtraS=$(( $DiffS-$DiffM*60 ))
ExtraM=$(( $DiffM-$DiffH*60 ))

# продолжительность в разных единицах
echo ${DiffS}s
echo ${DiffM}m
echo ${DiffH}h

# в минутах и секундах (минут может быть больше 60)
echo ${DiffM}:${ExtraS}"(m:s)"
# в часах, минутах и секундах
echo ${DiffH}:${ExtraM}:${ExtraS}"(h:m:s)"

Например:

$ timediff.sh 8:45 13:30
17100s
285m
4h
285:0(m:s)
4:45:0(h:m:s)


среда, 2 сентября 2015 г.

Особенности арифметики в bash: системы счисления

Краткое содержание: надо учитывать или явно указывать систему счисления.

Простая задача: найти, какой месяц был 7 месяцев назад.
Любым способом получаем текущий месяц, например:

(дальше использованы фрагменты рабочего скрипта, поэтому много излишеств, удалены некоторые другие команды, которые этими излишествами активно используются)

# лишняя переменная tSA только для удобства, чтобы не появились ошибки из-за
# неправильного экранирования вложенных команд
tSA=`date +%s`
# сегодня
todaySA=`date -d @$tSA +%Y%m%d`
# месяц сегодня
motSA=${todaySA:4:2}


Если месяц меньше 10, то в переменную motSA попадает значение вида 0N, где N - номер месяца с добавленным ведущим нулём. Всё красиво и гладко.Теперь находим искомое:

curmo=$motSA
echo curmo=$curmo
oldermo=$[curmo-7]
echo oldermo=$oldermo


Однако же... На дворе сентябрь, а значит curmo=09. По логике, 7 месяцев назад был февраль. Казалось бы, чего проще:

oldermo=$[curmo-7] ==> oldermo=$[09-7]

Однако, вместо oldermo=2 получаем ошибку:

$ curmo=09;echo $[curmo-7]
bash: 09: значение слишком велико для основания (ошибочная метка "09")


Мать моя женщина! Что за нафиг? Роемся в памяти и вспоминаем, что в некоторых языках программирования число с ведущим нулём считается заданным не в десятичной системе. В каком-то из ассемблеров ведущий ноль указывал на восьмеричную систему счисления (СС), и там вылезла бы подобная ошибка, потому как восьмеричные цифры от нуля до семёрки.
Начинаем курить мануал по bash и без проблем находим упоминание про base, hexadecimal, octal и т.п. В языке FORTH есть специальная конструкция, позволяющая временно изменить основание системы счисления (ОСС)в пределах текущего (под)выражения, что-то подобное должно быть и в bash. Точно, есть.

Для указания СС, в которой записано число, перед этим числом ставим префикс, в котором указываем десятичное значение ОСС. Например, 16 для шестнадцатиричной:

$ a=$[16#20];echo $a; a=$[8#20];echo $a;
32
16


По умолчанию bash распознает восьмеричную и шестнадцатеричную СС по префиксам 0 и 0x соответственно. Есть и некоторые другие особенности (знак "меньше" в сочетании "greater< than 9" не мой - скопировано из мануала к bash 4.3.11, для версии 4.2.25 такой ошибки нет):

Constants  with  a  leading 0 are interpreted as octal numbers.  A leading 0x or 0X denotes hexadecimal.  Otherwise, numbers take the form [base#]n, where the optional base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base.  If base# is omitted,  then  base 10  is  used.  When specifying n, the digits greater< than 9 are represented by the lowercase letters, the uppercase letters, @, and _, in that order.  If base is less than or equal to 36, lowercase and uppercase letters may be used interchangeably to represent numbers between 10 and 35.

Ладно, с ОСС разобрались, тестовый пример работает:

$ echo $[10#09-7]
2


И тут снова вылезает злосчастное "однако":

$ curmo=09;echo $[10#curmo-7]
bash: 10#curmo: значение слишком велико для основания (ошибочная метка "10#curmo")


На этот раз ошибка в том, что с указанием ОСС имя переменной перестает восприниматься как имя, а считается просто числом, записанным в указанной СС. Но в десятичке нет цифр c, m, o, r или u. Придется разыменовывать переменную:

$ curmo=09;echo $[10#$curmo-7]
2


Ура!

пятница, 27 июля 2012 г.

О калькуляторах командной строки

Есть в этих ваших линуксах хорошая штука, называется dc - RPN-калькулятор. Но при всех его фишках, имеет он и ряд недостатков. Нет, RPN к ним не относится - я когда-то игрался с FORTH-ом и с ПМК "Электроника" (например, МК-61), и такой синтаксис мне понятен и удобен. Но вот некоторых функций не достает.

А тут гугл выкатил объяву об усовершенствовании своего поискового калькулятора и в качестве примера предложил посчитать, сколько будет "6 пи делить на 4". Каждый извращался по своему в комментах, кто-то считал в гугле, кто-то в уме... Один товарисч воспользовался возможностаями оболочки bash. Я попробовал посчитать в dc и понял, что ни фига не выйдет, ибо константы "пи" в нем нет, как нет и тригонометрических функций. Надеясь, что это я что-то проглядел, я кинулся к великому и могучему с вопросом: "trigonometric in dc calculator, да?", на что он ответил такой вот ссылкой: "dc не поддерживает тригонометрию". И по той же ссылке мне кагбэ намекаэ, что есть и bc, поддерживающий стандартную математическую библиотеку...

Надо это учесть.

понедельник, 6 июня 2011 г.

Решатель уравнений и не только - WolframAlpha


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

WolframAlpha - photon energy ruby laser

Вот пример такого расчета:

Ну а для таких расчетов я в свое время писал программу для МК-61. Только моя программа выдавала еще диаметры вписанной в треугольник и описанной около него окружностей.