eddy_em: (Default)
[personal profile] eddy_em
Сижу, ковыряю отчет (который, кстати, теоретически должен был делать не я…).
И вот, пришла мне в голову мысль: а почему бы не включить кое-какие простые расчеты прямо сразу в этот отчетец? Ведь есть же пакет fp, позволяющий производить простые операции с плавающими числами (и даже решать уравнения). Правда, время компиляции документа при этом несколько увеличивается, но зато не нужно будет 100500 раз проверять свой документ после изменения одного-двух параметров.


До этого я уже сделал небольшую заготовку - команду \Ins, которая принимает либо 1 параметр, либо не принимает их вообще. Параметр (или пустое место, если параметра нет) обводится красной рамочкой и на полях рисуется красный квадратик - мол, обрати внимание!
Теперь я решил сделать так, чтобы эта команда \Ins принимала от нуля до двух параметров, а также имела два режима: "черновик" и "чистовик". В режиме "черновик" \Ins с 0 или 1 параметром ведет себя, как и прежде, а вот с двумя параметрами - как \Ins{#2}, но при этом еще и присваивает первому параметру значение второго. В режиме "чистовик", который пока определяется командой \def\TextOut{} (а вообще, если все это оформить отдельным пакетом, можно сделать опцию пакета draft), красные рамочки рисуются лишь в случае, когда у \Ins нет параметров (т.е. мы что-то явно забыли или забили).

Итак, код:

\makeatletter
\ifx\TextOut\undefined
	\def\InsTxt@#1{\red{\fbox{#1}}\marginpar{\red{\Square}}}
\else
	\def\InsTxt@#1{#1}
\fi
\def\InsWFP#1#2{\expandafter\FPset\csname#1\endcsname{#2}\InsTxt@{#2}}
\def\Ins{\futurelet\next\Ins@i}
\def\Ins@i{\ifx\next\bgroup\expandafter\Ins@ii\else\expandafter\Ins@end\fi}
\def\Ins@ii#1{\def\temp@rg{#1}\futurelet\next\Ins@iii}
\def\Ins@iii{\ifx\next\bgroup\expandafter\Ins@two@rgs%
\else\expandafter\Ins@one@rg\fi}
\def\Ins@two@rgs#1{\InsWFP{\temp@rg}{#1}} % Two args
\def\Ins@one@rg{\InsTxt@{\temp@rg}} %One arg
\def\Ins@end{\red{\fbox{\phantom{text}}}\xspace\marginpar{\red{\Square}}}
\def\FPrint#1{\@@print@@#1}
\def\@@print@@#1:#2{\FPeval{\res@lt}{round(#1:2)}\res@lt}
\makeatother


Поясню, что делается в коде выше. Команда \Ins перенаправляет латех, не "проглатывая" аргументов, на команду \Ins@i. Та проверяет, идет ли после нее символ \bgroup (открывающаяся фигурная скобка). Если идет - значит, у нашей команды есть как минимум 1 аргумент - переходим к команде \Ins@ii, иначе (аргументов нет) - переходим к команде \Ins@end.
Команда \Ins@ii уже имеет один аргумент (мы его "проглотили" в предыдущей команде), поэтому его мы помещаем во временную переменную \temp@rg и опять проверяем - есть ли аргументы дальше, переходя к команде \def\Ins@iii. Там мы выполняем либо \Ins@two@rgs (если аргументов два), либо \Ins@one@rg (если он один).
Команда \Ins@two@rgs выполняет \InsWFP, которая, в свою очередь, присваивает первому аргументу (он, кстати, является обычным текстом, а не командой - для того, чтобы из него сделать команду, как того требует пакет fp, мы и используем \csname) второй аргумент, а затем выводит при помощи \InsTxt@ второй аргумент в итоговый документ.
Команда \Ins@one@rg просто выводит свой аргумент в документ.
Команда вывода \InsTxt@ зависит от нашего флага "черновика": если он установлен, мы выбрасываем текст в рамке и делаем пометку на полях, иначе - текст без рамки.
Команда \Ins@end выводит пустую рамку в любом режиме (т.к. явно если она не имеет аргумента в режиме "чистовика", это значит, что мы этот аргумент вставить забыли).
Еще я добавил команду \FPrint, позволяющую проводить вычисления в тексте и сразу же выдавать ответ в документ. Аргумент этой команды имеет вид вычисления:точность, где "вычисления" - какие-то операции, а "точность" - количество знаков после запятой (все результаты надо округлять, иначе получите огромное количество нулей после запятой даже в целом числе).

В результате из вот такого

Пусть гипотенузы треугольника равны a=\Ins{a}{2.5}, b=\Ins{b}{3}, тогда
катет будет равен $c=\sqrt{a^2+b^2}=\FPrint{root(2, (a^2 + b^2)):2}$

мы получаем:


Upd:

Сделал покрасивше и удобней (счетчик завел):

\makeatletter
\newcounter{InsC@unt@r}
\def\Ind@x{\stepcounter{InsC@unt@r}%
			\hbox to 0pt{\raisebox{1ex}{\tiny\red{\arabic{InsC@unt@r}}}}}
\def\Insm@rgimp@r#1{\marginpar{\red{\tiny\arabic{InsC@unt@r}:#1}}}
\ifx\TextOut\undefined
	\def\InsTxt@#1#2{#1\Ind@x\Insm@rgimp@r{#2}}
\else
	\def\InsTxt@#1{#1}
\fi
\def\InsWFP#1#2{\expandafter\FPset\csname#1\endcsname{#2}\InsTxt@{#2}{#1}}
\def\Ins{\futurelet\next\Ins@i}
\def\Ins@i{\ifx\next\bgroup\expandafter\Ins@ii\else\expandafter\Ins@end\fi}
\def\Ins@ii#1{\def\temp@rg{#1}\futurelet\next\Ins@iii}
\def\Ins@iii{\ifx\next\bgroup\expandafter\Ins@two@rgs%
\else\expandafter\Ins@one@rg\fi}
\def\Ins@two@rgs#1{\InsWFP{\temp@rg}{#1}} % Two args
\def\Ins@one@rg{\InsTxt@{\temp@rg}{}} %One arg
\def\Ins@end{\red{\Square\Ind@x}\Insm@rgimp@r{?}\xspace}
\def\FPrint#1{\@@print@@#1}
\def\@@print@@#1:#2{\FPeval{\res@lt}{round(#1:2)}\res@lt}
\makeatother



This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org

April 2025

S M T W T F S
  1 23 45
67 89101112
13141516171819
20212223242526
27282930   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 23rd, 2025 02:31 am
Powered by Dreamwidth Studios