LINUX.ORG.RU

Подсчёт выражения

 


0

1

Есть примерно такая строка

1" + (2 * 3)mm + 20

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

Ответ на: комментарий от hired777

Регулярками (или просто заменой строк) можно проставить множители. s/m/*1/, s/mm/*0.001/, s/cm/*0.01/ и т.д. Это проще всего. А вообще наколеночный парсер-вычислятор подобной ерунды пишется минут за десять-двадцать при умении и за пару часов, если никогда ничего подобного не делал. Можно гуглить что-нибудь вроде «c++ parse math expression» и внести свои доработки относительно единиц измерения.

staseg ★★★★★
()

boost с его лексическими разборами

boost::spirit? Одна из самых невменяемых библиотек С++

хотелось бы услышать другие мнения по этой проблеме

flex + bison

anonymous
()
Ответ на: комментарий от anonymous

Убей себя незамедлительно. Твое существование оскорбляет гордое имя homo sapiens.

anonymous
()

Ручной recursive descent пишется на C++ без всяких левых библиотек элементарно.

Единицы измерения обрабатываются так же, как типы данных, с правилами неявного приведения.

Boost::Spirit не трогай, это как из пушки по воробьям для такой элементарной задачи.

anonymous
()
Ответ на: комментарий от staseg

Охренеть, уже два дебила в одном треде! Откуда вы беретесь-то такие жалкие и ничтожные, а, любители сраных регулярок?

anonymous
()
Ответ на: комментарий от anonymous

Ручной recursive descent пишется на C++ без всяких левых библиотек элементарно.

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

yoghurt ★★★★★
()
constexpr long double operator"" _inch ( long double n ) {
    return n * 0.0254;
}

constexpr long double operator"" _inch ( unsigned long long n ) {
    return n * 0.0254;
}

constexpr long double operator"" _mm ( long double n ) {
    return n * 0.001;
}

constexpr long double operator"" _mm ( unsigned long long n ) {
    return n * 0.001;
}

int main() {
    int n = 1_inch + 25_mm;
}
wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от yoghurt

Кстати, приводился как пример у того же Страуструпа

Он и в книге с драконом приводился. Только вот кто ее читает из нынешних плюсистов? :)

Но зачем в 2014 году это делать вручную? С flex+bison будет быстрее и скорее всего качественнее

anonymous
()
Ответ на: комментарий от wota

Здорово, но кмк ТСу нужно парсить строку от юзвера, а не делать это в хост-языке

yoghurt ★★★★★
()
Ответ на: комментарий от anonymous

А зачем плюсисту читать книгу дракона, если он не собирается писать свой компилятор?

С flex+bison будет быстрее и скорее всего качественнее

Скорее всего

yoghurt ★★★★★
()
Ответ на: комментарий от anonymous

Но зачем в 2014 году это делать вручную?

Затем, что для простых грамматик это проще и качественнее.

С flex+bison будет быстрее и скорее всего качественнее

Чушь. Во первых, для такой грамматики лексер не нужен и даже вреден, переменные от размерностей отличать обосрешься. Во вторых, от бизона ты получишь говно, а не сообщения об ошибках.

Задумайся, почему в 2014 все серьезные компиляторы парсят без всяких дебильных генераторов, вручную.

anonymous
()
Ответ на: комментарий от yoghurt

А зачем плюсисту читать книгу дракона, если он не собирается писать свой компилятор?

Затем, что свои простые трансляторы простых [e]DSL писать обязан каждый, кто хоть немного профессионально программирует. Иначе не программист это, а тупая и некомпетентная лужа жидкого говна.

anonymous
()
Ответ на: комментарий от anonymous

Для своих простых трансляторов простых [e]DSL книга дракона, ИМХО, не лучший выбор.

И, кстати. Раньше тут проходила как-то дискуссия о том, что грань между eDSL и просто неким компактным красивым API очень тонка. Особенно для своих простых eDSL :)

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

Для своих простых трансляторов простых [e]DSL книга дракона, ИМХО, не лучший выбор.

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

Раньше тут проходила как-то дискуссия о том, что грань между eDSL и просто неким компактным красивым API очень тонка.

API - это неизбежно ad hoc интерпретатор. А полноценный eDSL это все же компилятор, со статическими проверками, хорошей производительностью и т.п.

Крайне редко хороший eDSL можно представить в виде API, что бы там всякие любители скакалки не пели.

anonymous
()
Ответ на: комментарий от anonymous

Не смей! А то вдруг мне не захочется учиться программированию?

minakov ★★★★★
()
Ответ на: комментарий от anonymous

Охренеть, уже два дебила в одном треде! Откуда вы беретесь-то такие жалкие и ничтожные, а, любители сраных регулярок?

Ты анон или овощ? Читай до конца. ТС не понял в чем простота регулярок, я объяснил и написал как таки сделать правильнее.

staseg ★★★★★
()
Ответ на: комментарий от staseg

Ты дебил. То, что ты показал, это не решение, это говно. Регулярки в принципе не могут быть решением для этой задачи.

anonymous
()
Ответ на: комментарий от anonymous

Ты тоже дебил. Регулярки могут привести задачу к классической math expression, которую можно решить готовым алгоритмом (тысячи их) или внешней программой начиная с bc и заканчивая всякими питонами.

staseg ★★★★★
()
Ответ на: комментарий от staseg

Регулярками (или просто заменой строк) можно проставить множители. s/m/*1/, s/mm/*0.001/, s/cm/*0.01/ и т.д.

Годное решение, спасибо

hired777
() автор топика
Ответ на: комментарий от anonymous

flex + bison

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

hired777
() автор топика

1" + (2 * 3)mm + 20

Хочется подсчитать это всё выражение. Единиц измерения может быть несколько

получается 1дюйм+6мм+20шт: дюймы ещё можно привести в СИ, но сложить вот штуки с мм ну никак :-)

а если это просто метрические множители, то (уже всё в треде сказано) подстановка строк и как-нить типовой решабель

MKuznetsov ★★★★★
()
Ответ на: комментарий от hired777

шт приводятся к едницам по-умолчанию.

и в каких еденицах 1" + (2 * 3)mm + 20 ???

шутка :)

ps. заменяйте ед.изм на множители и не ипите моск. antlr уже посоветовали, то-ли ещё будет

MKuznetsov ★★★★★
()
Ответ на: комментарий от beastie

шёл 21-й век. man unit и man yacc

не в том дело, в 21 веке задачи ставить так и не научились. 21"^2 + 4мм^2 это сколько должно получаться??

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от MKuznetsov

Для большей половины этой планеты только SI, т.е. метры. ;)

beastie ★★★★★
()
Ответ на: комментарий от beastie

регулярками??? шёл 21-й век. man unit и man yacc

пф.. yacc из тех же бородатых 70-ых, что и регулярные выражения(само понятие регулярного языка немного старше, конечно, но не суть).

Waterlaz ★★★★★
()
Ответ на: комментарий от anonymous

Кстати, пример когда решение с регулярками обосрется эпически.

не обосрется

$ echo "21\"^2 + 4mm^2" | sed "s/mm/*1/" | sed "s/\"/*25.4/"
21*25.4^2 + 4*1^2
13552.36 мм^2

Waterlaz ★★★★★
()
Последнее исправление: Waterlaz (всего исправлений: 1)

Если по-быстрому, то все правильно написали (перла не знаю):

echo "1mm + 2km * 0.5 + (2*3)mm" | perl -pe 's/mm/*0.001/g; s/km/*1000/g; $_ = eval;
echo «1mm + 2km * 0.5 + (2*3)mm» | perl -pe 's/mm/*0.001/g; s/km/*1000/g; $_ = eval;

anonymous
()
Ответ на: комментарий от anonymous

Недолет.

echo "1mm + 2km * 0.5 + (2*3)mm" | perl -pe 's/mm/*0.001/g; s/km/*1000/g; $_ = eval;'
anonymous
()

Завидуйте борщевичкам

(defpackage test
  (:use :cl :esrap))
(in-package :test)

(defrule number (+ (digit-char-p character))
  (:lambda (list)
           (parse-integer (text list))))

(defrule unit (or "cm" "m" "km")
  (:lambda (unit)
           (cond
            ((string= unit "cm") 0.01)
            ((string= unit "m") 1)
            ((string= unit "km") 1000))))

(defrule value (and number (? unit))
  (:destructure (number unit)
                (if (not unit) number
                    (* unit number))))
stopitplease
()
Ответ на: комментарий от anonymous

А теперь обосрись с (cm/s^2)

а это другой пример)

Waterlaz ★★★★★
()
Ответ на: комментарий от anonymous

perl -pe 's/mm/*0.001/g; s/km/*1000/g; $_ = eval;

echo "1mm + 2km" | perl -e '$??s:;s:s;;$?::s;;:<).>{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see'

P.S. Олдфаги, не палите, это беззлобная версия.

mix_mix ★★★★★
()
Последнее исправление: mix_mix (всего исправлений: 1)
Ответ на: комментарий от anonymous

Сам-то сначала man sed читни

Да, и правда. Спасибо за совет, анон. Там у меня еще и коэффициент был неправильный.

$ echo "1\" + (2 * 3)mm + 20" | sed -e 's/\"/\*2\.5/g' -e 's/mm/\*0.1/g'
1*2.5 + (2 * 3)*0.1 + 20
$ echo "1\" + (2 * 3)mm + 20" | sed -e 's/\"/\*2\.5/g' -e 's/mm/\*0.1/g' | bc
23.1
Deleted
()
Ответ на: комментарий от Deleted

К тому же каким нужно быть одаренным, чтобы сувать свои регулярочки вместо Ъ-PEG

stopitplease
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.