发票小计计算精度损失

发票小计计算精度损失

在此处输入图片描述 小计应为 330 美元,但显示为 329.70 美元。

我正在使用此发票包 https://github.com/treyhunner/invoices/blob/master/invoice.cls

我的发票表行如下:

\documentclass{invoice}

\def \tab {\hspace*{3ex}}

\begin{document}

\hfil{\Huge\bf me}\hfil
\bigskip\break % Whitespace
\hrule % Horizontal line

my address \hfill (999) 111-2222 \\
my address \hfill [email protected]
\\ \\
{\bf Invoice To:} \\
\tab client \\
\tab client address \\

{\bf Date:} \\
\tab \today \\

\begin{invoiceTable}

\feetype{Consulting Services}

\hourrow{2016-09-27}{0.3}{150}
\hourrow{2016-09-26}{0.1}{150}
\hourrow{2016-09-25}{1.2}{150}
\hourrow{2016-09-09}{0.1}{150}
\hourrow{2016-08-23}{0.2}{150}
\hourrow{2016-08-19}{0.3}{150}

\subtotal

\end{invoiceTable}

\end{document}

什麼?

答案1

该类在计算中使用了(高度准确)和(严重不准确)invoice的错误混合,因此预计会出现舍入误差。fpcalc

这是该类的修复版本。

%%% modified by egreg for TeX.Stackexchange
%%% http://tex.stackexchange.com/questions/331898/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Copyright (c) 2011 Trey Hunner                                          %
%                                                                          %
%  Permission is hereby granted, free of charge, to any person obtaining   %
%  a copy of this software and associated documentation files (the         %
%  "Software"), to deal in the Software without restriction, including     %
%  without limitation the rights to use, copy, modify, merge, publish,     %
%  distribute, sublicense, and/or sell copies of the Software, and to      %
%  permit persons to whom the Software is furnished to do so, subject to   %
%  the following conditions:                                               %
%                                                                          %
%  The above copyright notice and this permission notice shall be          %
%  included in all copies or substantial portions of the Software.         %
%                                                                          %
%  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,         %
%  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF      %
%  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                   %
%  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE  %
%  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION  %
%  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION   %
%  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.         %
%                                                                          %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ProvidesClass{invoice3}

\LoadClass[12pt]{article}

\usepackage[letterpaper,hmargin=0.79in,vmargin=0.79in]{geometry}
\usepackage[parfill]{parskip} % Do not indent paragraphs
\usepackage{xparse} % Fixed-point arithmetic, among many other things
\usepackage{siunitx} % for displaying numbers
\usepackage{longtable}

\pagestyle{empty} % No page numbers
\linespread{1.5}

\setlength{\doublerulesep}{\arrayrulewidth} % Double rules look like one thick one

% Command for setting a default hourly rate
\ExplSyntaxOn
\NewDocumentCommand{\hourlyrate}{m}
 {
  \fp_set:Nn \l_invoice_hourlyrate_fp { #1 }
 }
\fp_new:N \l_invoice_hourlyrate_fp
\hourlyrate{1} % initialize

\NewDocumentCommand{\feetype}{m}
 {
  \textbf{#1} \\
 }

% Counters for totaling up hours and dollars
\fp_new:N \g_invoice_hours_fp
\fp_new:N \g_invoice_subhours_fp
\fp_new:N \g_invoice_cost_fp
\fp_new:N \g_invoice_subcost_fp

% Formats input number with 2 digits after the decimal place
\NewDocumentCommand{\formatNumber}{m}
 {
  \num[detect-all,round-integer-to-decimal,round-mode=places,round-precision=2]{\fp_eval:n {#1}}
 }

% Returns the total of counter
\NewDocumentCommand{\total}{m}
 {
  \formatNumber{#1}
 }

% Create a new row from title, unit quantity, unit rate, and unit name
\NewDocumentCommand{\unitrow}{mmmm}
 {
  \fp_gadd:Nn \g_invoice_cost_fp { (#2) * (#3) }
  \fp_gadd:Nn \g_invoice_subcost_fp { (#2) * (#3) }
  #1 &
  \formatNumber{#2} ~ #4 &
  \$\formatNumber{#3} &
  \$\formatNumber{#2 * #3}
  \\
 }
% Create a new row from title and expense amount
\NewDocumentCommand{\feerow}{mm}
 {
  \fp_gadd:Nn \g_invoice_cost_fp { #2 }
  \fp_gadd:Nn \g_invoice_subcost_fp { #2 }
  #1 & & \$\formatNumber{#2} & \$\formatNumber{#2} \\
 }
\DeclareExpandableDocumentCommand{\subtotal}{}
 {
  \hline
  \subtotalaux
 }
\NewDocumentCommand{\subtotalaux}{s}
 {
  \textbf{Subtotal} &
  \IfBooleanF{#1}{\textbf{\total{\g_invoice_subhours_fp} ~ hours}} &
  &
  \textbf{\$\formatNumber{\g_invoice_subcost_fp}}
  \fp_gzero:N \g_invoice_subcost_fp
  \IfBooleanF{#1}{\fp_gzero:N \g_invoice_subhours_fp}
  \\*[1.5ex]
 }
% Create a new row from date and hours worked (use stored fee type and hourly rate)
\NewDocumentCommand{\hourrow}{mm}
 {
  \fp_gadd:Nn \g_invoice_hours_fp { #2 }
  \fp_gadd:Nn \g_invoice_subhours_fp { #2 }
  \unitrow{#1}{#2}{\l_invoice_hourlyrate_fp}{hours}
 }

% Create an invoice table
\NewDocumentEnvironment{invoiceTable}{}
 {
  \setlength{\tabcolsep}{0.8ex}
  \setlength\LTleft{0pt}
  \setlength\LTright{0pt}
  \begin{longtable}{@{\extracolsep{\fill}\hspace{\tabcolsep}} l r r r }
  \hline
  \textbf{Description~of~Services} &
  \multicolumn{1}{c}{\bfseries Quantity} &
  \multicolumn{1}{c}{\bfseries Unit~Price} &
  \multicolumn{1}{c}{\bfseries Amount} \\*
  \hline\hline
  \endhead
 }
 {
  \\*[-\normalbaselineskip]
  \hline\hline\hline
  {\bfseries Balance Due} & & & {\bfseries \$\formatNumber{\g_invoice_cost_fp}} \\
  \end{longtable}
 }
\ExplSyntaxOff

如果您将示例文件修改为

\documentclass{invoice3} % Use the custom invoice class (invoice.cls)

\begin{document}

\hourlyrate{150}

\begin{invoiceTable}
\feetype{Consulting Services}
\hourrow{2016-09-27}{0.3}
\hourrow{2016-09-26}{0.1}
\hourrow{2016-09-25}{1.2}
\hourrow{2016-09-09}{0.1}
\hourrow{2016-08-23}{0.2}
\hourrow{2016-08-19}{0.3}
\subtotal
\end{invoiceTable}

\end{document}

这些数字是正确的。

在此处输入图片描述

fp这是另一个仅使用并避免舍入问题的版本。

%%% modified by egreg
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Copyright (c) 2011 Trey Hunner                                          %
%                                                                          %
%  Permission is hereby granted, free of charge, to any person obtaining   %
%  a copy of this software and associated documentation files (the         %
%  "Software"), to deal in the Software without restriction, including     %
%  without limitation the rights to use, copy, modify, merge, publish,     %
%  distribute, sublicense, and/or sell copies of the Software, and to      %
%  permit persons to whom the Software is furnished to do so, subject to   %
%  the following conditions:                                               %
%                                                                          %
%  The above copyright notice and this permission notice shall be          %
%  included in all copies or substantial portions of the Software.         %
%                                                                          %
%  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,         %
%  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF      %
%  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                   %
%  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE  %
%  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION  %
%  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION   %
%  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.         %
%                                                                          %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ProvidesClass{invoice}

\LoadClass[12pt]{article}

\usepackage[letterpaper,hmargin=0.79in,vmargin=0.79in]{geometry}
\usepackage[parfill]{parskip} % Do not indent paragraphs
\usepackage{fp} % Fixed-point arithmetic
\usepackage{longtable}

\pagestyle{empty} % No page numbers
\linespread{1.5}

\setlength{\doublerulesep}{\arrayrulewidth} % Double rules look like one thick one

% variables for total cost and subcost, total hours and subhours
\def\totalcost{0}\def\subcost{0}
\def\totalhours{0}\def\subhours{0}

% Command for setting a default hourly rate
\newcommand{\hourlyrate}[1]{\def \@hourlyrate {#1}}
\hourlyrate{1}
\newcommand{\feetype}[1]{
    \textbf{#1}
    \\
}

% Formats inputed number with 2 digits after the decimal place
\newcommand*{\formatNumber}[1]{\FPround{\temp}{#1}{2}\temp} %

% Returns the total of counter
\newcommand*{\total}[1]{\formatNumber{#1}}

% Create an invoice table
\newenvironment{invoiceTable}{%
    % Create a new row from title, unit quantity, unit rate, and unit name
    \newcommand*{\unitrow}[4]{%
         \FPmul{\tempa}{##2}{##3}%
         \FPadd{\tempb}{\totalcost}{\tempa}%
         \global\let\totalcost\tempb
         \FPadd{\tempb}{\subcost}{\tempa}%
         \global\let\subcost\tempb
         ##1 & \formatNumber{##2} ##4 & \$\formatNumber{##3} & \$\FPmul{\temp}{##2}{##3}\formatNumber{\temp}%
         \\
    }%
    % Create a new row from title and expense amount
    \newcommand*{\feerow}[2]{%
         \FPadd{\tempa}{\totalcost}{##2}%
         \global\let\totalcost\tempa
         \FPadd{\tempa}{\subcost}{##2}%
         \global\let\subcost\tempa
         ##1 & & \$\formatNumber{##2} & \$\formatNumber{##2}%
         \\
    }%
    \newcommand{\subtotalNoStar}{%
        \textbf{Subtotal} & \textbf{\total{\subhours} hours} &  & \textbf{\$\total{\subcost}}%
        \gdef\subcost{0}%
        \gdef\subhours{0}%
        \\*[1.5ex]
    }%
    \newcommand{\subtotalStar}{%
        \textbf{Subtotal} & & & \textbf{\$\total{\subcost}}
        \gdef\subcost{0}%
        \\*[1.5ex]
    }%
    \newcommand{\subtotal}{%
         \hline
         \@ifstar
         \subtotalStar
         \subtotalNoStar
    }%
    % Create a new row from date and hours worked (use stored fee type and hourly rate)
    \newcommand*{\hourrow}[2]{%
        \FPadd{\tempa}{\totalhours}{##2}%
        \global\let\totalhours\tempa
        \FPadd{\tempa}{\subhours}{##2}%
        \global\let\subhours\tempa
        \unitrow{##1}{##2}{\@hourlyrate}{hours}%
    }%
    \setlength{\tabcolsep}{0.8ex}%
    \setlength\LTleft{0pt}%
    \setlength\LTright{0pt}%
    \begin{longtable}{@{\extracolsep{\fill}\hspace{\tabcolsep}} l r r r }
    \hline
    \bfseries Description of Services & \multicolumn{1}{c}{\bfseries Quantity} & \multicolumn{1}{c}{\bfseries Unit Price} & \multicolumn{1}{c}{\bfseries Amount} \\*
    \hline\hline
    \endhead
}{
    \hline\hline\hline
    \bfseries Balance Due & & & \bfseries \$\total{\totalcost} \\
    \end{longtable}
}

相关内容