在 LaTeX 中计算直角三角形边长

在 LaTeX 中计算直角三角形边长

我想在 LaTeX 文档中根据屏幕的对角线和纵横比计算屏幕的宽度。该公式很容易从勾股定理得出,但需要平方根。

我目前使用calc计算平方根的包来计算巴比伦方法,但它不太优雅。在 latex 中计算平方根(和其他函数)的最佳方法是什么?

答案1

这是一个有趣的问题。首先我们需要比较和分析一些答案

1)使用 Lua:这是未来,而且非常准确,但不幸的是它使用得不够多,而且很多 TeX 用户只使用 pdf(la)TeX。

2)fp解决方案很好,但我们需要谨慎使用,因为这可能会很慢。这是我喜欢的方法。但fp如果您需要获得的结果,则可能会出现问题(-1.5)^(2)

下一个代码来自我修改的 Christian Tellechea 2009。

\documentclass{scrartcl}
\usepackage{fp}   
\makeatletter  
\def\FP@pow#1#2#3{%
 \FP@beginmessage{POW}%
 {\def\FP@beginmessage##1{}%
 \def\FP@endmessage##1{}%
 \FPifzero{#2}%
     \expandafter\@firstoftwo
 \else
     \expandafter\@secondoftwo
 \fi
 {\FP@pow@zero{#3}}%
 {\FPifint{#3}%
     \expandafter\@firstoftwo
 \else
    \expandafter\@secondoftwo
 \fi  
{\FPifneg{#2}%
 \FPneg\FP@tmpd{#2}%
 \FPln\FP@tmpd\FP@tmpd
 \FPmul\FP@tmpd\FP@tmpd{#3}%
 \FPexp\FP@tmpd\FP@tmpd
 \FPtrunc\FP@tmp{#3}0%
 \ifodd\FP@tmp
     \FPneg\FP@tmp\FP@tmpd
 \else
     \let\FP@tmp\FP@tmpd
 \fi
\else
 \FPln\FP@tmpd{#2}%
 \FPmul\FP@tmpd\FP@tmpd{#3}%
 \FPexp\FP@tmp\FP@tmpd
\fi
}% 
{\FPln\FP@tmpd{#2}%
 \FPmul\FP@tmpd\FP@tmpd{#3}%
 \FPexp\FP@tmp\FP@tmpd}%
}%
\global\let\FP@tmp\FP@tmp}%
\FP@endmessage{}%
\let#1\FP@tmp}    
\makeatletter
\begin{document}

\FPpow\temp{-1.5}{2}
\temp 

\FPpow\temp{-2}{3}
\temp 
\end{document}  

3)pgfmath。Martin 的回答描述了传统方法。对于极值,它也可能很慢,有时不准确。下图说明了有时使用 会导致不准确的结果pgfmath。图片来自段落中的 pgfmanual投影修改器的语法。三个高度的交点在较小尺寸下没有问题,但使用大缩放我们得到以下结果:

在此处输入图片描述

4)有了fpu。就可以使用fpu里面有一个包pgf

\documentclass{article} 
\usepackage{tikz}
\usepackage{fp}   
\usetikzlibrary{fpu}
\newlength{\lengtha}
\newlength{\lengthb}  
\begin{document} 

\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed} 
\setlength{\lengtha}{1pt}
\setlength{\lengthb}{1pt}
\pgfmathparse{sqrt(\lengtha*\lengtha + \lengthb*\lengthb)}
\pgfmathresult 
\end{document}

结果是 1.414192000000000。这很奇怪,因为pgfmath在这种情况下给出的是 1.41421,而fp使用相同的值则给出 1.414213562373095042。

5)\usetikzlibrary{fixedpointarithmetic} 另一种可能是fixed point arithmetic。它又在里面pgf

\documentclass{article} 
\usepackage{tikz}
\usepackage{fp}   
\usetikzlibrary{fixedpointarithmetic} 
\newlength{\lengtha}
\newlength{\lengthb}  
\begin{document}      
\setlength{\lengtha}{1pt}
\setlength{\lengthb}{1pt}
\pgfkeys{/pgf/fixed point arithmetic={scale results=10^-6}} 
\pgfmathparse{sqrt(\lengtha*\lengtha + \lengthb*\lengthb)}
\pgfmathresult  
\end{document}

结果与 一样fp,正常fp使用 !! result = 1.414213562373095042

6)\usepackage{tkz-euclide} 当需要计算两个节点之间的距离时,可以使用我在我的包中定义的宏:tkz-euclide。它与的混合fp

\begin{tikzpicture}
\coordinate (A) at (3,0);
\coordinate (B) at (0,4);

 \tkzCalcLength[cm](A,B) 

 \node {\tkzLengthResult } ;
\draw (A) circle (\tkzLengthResult cm) ;
\draw[fill=red] (A) circle (2pt) ; 
\draw[fill=red] (B) circle (2pt) ;  
\end{tikzpicture}

\tkzLengthResult给出 5.00000 有一个选项可以以 pt 或 cm 为单位获取结果。

7) 最后使用最后一个解决方案TeX。此解决方案由朋友 J_C Charpentier 编写。这很有趣。宏被命名\pythagore,此宏使用另一个宏\SQRT来获取整数 < 1962446671 的平方根。

\documentclass{article}    
\makeatletter
\newcount\@tempcntc
\newcommand\SQRT[2]{%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % #2 = \sqrt{#1} (valeur entière)    %
  % #2 est une longueur                %
  % #1 ne doit pas dépasser 1962446671 %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Initialisations
  \@tempcnta #1\relax % Sauvegarde valeur
  \@tempcntb 1 % juste pour le premier test
  \@tempcntc #1\relax % Terme en cours
  % simili racine pour le premier terme !!!!
  \ifnum \@tempcntc > 1073741824 % 2^{30}
    \divide \@tempcntc 32738
  \else\ifnum \@tempcntc > 268435456 % 2^{28}
    \divide \@tempcntc 16384
  \else\ifnum \@tempcntc > 67108864 % 2^{26}
    \divide \@tempcntc 8192
  \else\ifnum \@tempcntc > 16777216 % 2^{24}
    \divide \@tempcntc 4096
  \else\ifnum \@tempcntc > 4194304 % 2^{22}
    \divide \@tempcntc 2048
  \else\ifnum \@tempcntc > 1048576 % 2^{20}
    \divide \@tempcntc 1024
  \else\ifnum \@tempcntc > 262144 % 2^{18}
    \divide \@tempcntc 512
  \else\ifnum \@tempcntc > 65536 % 2^{16}
    \divide \@tempcntc 256
  \else\ifnum \@tempcntc > 16384 % 2^{14}
    \divide \@tempcntc 128
  \else\ifnum \@tempcntc > 4096 % 2^{12}
    \divide \@tempcntc 64
  \else\ifnum \@tempcntc > 1024 % 2^{10}
    \divide \@tempcntc 32
  \else\ifnum \@tempcntc > 256 % 2^{8}
    \divide \@tempcntc 16
  \else\ifnum \@tempcntc > 64 % 2^{6}
    \divide \@tempcntc 8
  \else\ifnum \@tempcntc > 16 % 2^{4}
    \divide \@tempcntc 4
  \else\ifnum \@tempcntc > 4 % 2^{2}
    \divide \@tempcntc 2
  \else\ifnum \@tempcntc > 2 % 2^{1}
    % c'est 3 ou 4, l'arrondi est toujours 2
    \@tempcntc 2
    \@tempcntb 0 % pas de boucle !
  \else\ifnum \@tempcntc > 1
    % C'est 2, l'arrondi est 1
    \@tempcntc 1
    \@tempcntb 0 % pas de boucle !
  \else
    % c'est 0 ou 1 la racine est le nombre
    \@tempcntb 0 % pas de boucle !
  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi % joli !
  % Boucle principale (Newton)
  \loop
  \ifnum\@tempcntb>0
    % Calcul du terme suivant
    \@tempcntb \@tempcnta
    \divide \@tempcntb \@tempcntc
    \advance \@tempcntc \@tempcntb
    \divide \@tempcntc 2
    % On regarde où on en est
    % (différence entre l'itération au carré et le nombre initial)
    \@tempcntb \@tempcntc
    \multiply \@tempcntb \@tempcntb
    \advance \@tempcntb -\@tempcnta
  \repeat
  % Sauvegarde du résultat
  #2\the\@tempcntc sp\relax
}
\newcommand*\pythagore[3]{%
  \dimen0=#1\relax
  \@tempcnta \dimen0
  \dimen0=#2\relax
  \@tempcntb \dimen0
  % Pour éviter les débordements
  % on travaille en 1/32 de point
  \divide \@tempcnta 2048
  \divide \@tempcntb 2048
  % calcul de a*a+b*b
  \multiply \@tempcnta \@tempcnta
  \multiply \@tempcntb \@tempcntb
  \advance \@tempcnta \@tempcntb
  % appel de la racine
  \SQRT{\the\@tempcnta}{#3}%
  % Fin des débordements !
  #3 2048#3\relax
}
\makeatother

\newlength{\result}        
\begin{document} 

\pythagore{2pt}{2pt}{\result}
\the\result 

\pythagore{3pt}{4pt}{\result} 
\the\result

\pythagore{6pt}{8pt}{\result} 
\the\result 
\end{document}     

结果为:2.8125pt;5.0 pt 和 10.0pt

答案2

我会使用fp的幂函数来计算平方根等。借助fp的精度,您还可以将舍入误差最小化到接近 15 位小数。

考虑 10 的平方根。你可以将其写成幂函数:

\FPpow\temp{10}{0.5}

我们得到 3.162277660168379312

您访问宏中的值\temp(它可以是任何名称,fp将动态定义它)。

将其转换回 2 的幂,我们得到:

 \FPpow\temp{\temp}{2}
 \FPround\temp{\temp}{15}
 \temp

 10.000000000000000

最小显示如下:

\documentclass{article}
\usepackage{fp}
\begin{document}
\FPpow\temp{10}{0.5}
\temp

\FPpow\temp{\temp}{2}
\FPround\temp{\temp}{15}
\temp
\end{document}

使用的变量\temp会累积结果。无需扰乱命名空间。

答案3

您可以使用矢量图形包的数学功能PGF

\documentclass{article}
\usepackage{pgf}
\pgfmathsetmacro{\diagonal}{1280}
\pgfmathsetmacro{\aspectratio}{4/3}
\pgfmathsetmacro{\screenwidth}{(\diagonal*\aspectratio)/sqrt(\aspectratio^2+1)}
\begin{document}
    \screenwidth
\end{document}

不幸的是,结果是1024.0023,所以它不是绝对准确的。如果你只需要结果的整数部分,你可以使用\pgfmathtruncatemacro{\screenwidth}{(\diagonal*\aspectratio)/sqrt(\aspectratio^2+1)},它会截掉小数位。

答案4

您可以使用pgfmath(pgf包) 来为您提供一个sqrt功能。但是,就像 Harlad Hanche-Olsen 在他的评论中已经提到的那样,这取决于所需的精度。这使用了 TeX 长度寄存器的精度,这有其局限性。

例如:

\documentclass{article}

\usepackage{pgf}

\newlength{\lengtha}
\newlength{\lengthb}

\begin{document}

\setlength{\lengtha}{3pt}
\setlength{\lengthb}{5pt}

\pgfmathparse{sqrt(\lengtha*\lengtha + \lengthb*\lengthb)}
\pgfmathresult

\end{document}

相关内容