# Floating point equivalent of \int_case:nnTF

There are several typed pattern-matching commands in expl3, such as \tl_case, \str_case etc., including \int_case, but, notably, there doesn't seem to be a corresponding \fp_case for matching floating point values. I am using the current l3kernel documentation for reference.

Am I missing something trivial or is \fp_case actually missing at the moment? If so, I'd appreciate some pointers towards implementing it, as I'm still new at using LaTeX3 internals. TIA.

• It would be a bit pointless, because you can have rounding errors and then 3.1415926535897932 would not match 3.1415926535897931... – Phelype Oleinik Jun 11 '20 at 16:04
• The short answer is going to be 'there isn't one', but I wonder what you are up to where you feel a floating point 'case' switch makes sense – Joseph Wright Jun 11 '20 at 16:04
• @PhelypeOleinik That's true (also in C and other "conventional" languages), I was just wondering about the existence of \fp_compare and the possibility of expanding on the same idea. I might very well be misunderstanding something here, though. – Arets Paeglis Jun 11 '20 at 16:13
• @JosephWright Terrible things. – Arets Paeglis Jun 11 '20 at 16:13
• @AretsPaeglis With \fp_compare:nNnTF, you are often looking for 'more than X' or 'less than X', which doesn't have that issue. Or you are looking for reliable marker values (like exactly zero). – Joseph Wright Jun 11 '20 at 16:26

It doesn't exist because it doesn't make much practical sense. Any inaccuracy you get from a specific computation will make your code do a different thing, even if 3.1415926535897932 and 3.1415926535897931 aren't really different. For example, this:

\fp_compare:nNnTF { sin(2pi) } = { 0 }
{ \TRUE } { \FALSE }

yields false, even though analytically it should be true.

Floating-point equality is generally the wrong operation. Most of the time it works because floating-point engines are really good at their jobs, but if you feed them a tricky case it will get the wrong result. In fact, when I used to write Fortran code, gfortran would raise a compile-time warning about floating-point equality (I don't have it installed to give an example, sorry).

And the issue with \fp_case:nn would be that it would use only equality tests to select a case, and that could work, yes, but it could also go wrong, so mainly for stability, it doesn't exist.

That said, we do have \bool_case_true:n(TF) and \bool_case_false:n(TF), which you can use to emulate a \fp_case:nn which checks if a value matches within a set tolerance. Here's a proof-of-concept (no true/false branching implemented):

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\fp_new:N \l_arets_tol_fp
\fp_set:Nn \l_arets_tol_fp { 1e-6 }
\cs_new:Npn \arets_fp_case:nn #1
{
\exp_args:Nf \__arets_fp_case:nn
{ \fp_eval:n {#1} }
}
\cs_new:Npn \__arets_fp_case:nn #1#2
{
\tl_map_tokens:nn {#2}
{ \__arets_fp_case_split:nn {#1} }
}
\cs_new:Npn \__arets_fp_case_split:nn #1#2
{ \__arets_fp_case:nnn {#1} #2 }
\cs_new:Npn \__arets_fp_case:nnn #1#2#3
{
\fp_compare:nT
{
#1 > #2 - \l_arets_tol_fp &
#1 < #2 + \l_arets_tol_fp
}
{ \tl_map_break:n {#3} }
}

% ------------ Test macro
\cs_new_protected:Npn \test #1
{
$\arets_fp_case:nn {#1} { { { pi } { \pi } } { { exp(1) } { e } } } = \fp_eval:n {#1}$
}

\ExplSyntaxOff
\begin{document}
\test{3.1415926}

\test{2.7182818}

\test{1.6180339}
\end{document}

which prints:

• Thank you for the detailed response! I know about the issues with rounding in switch statements in general, I was wondering exactly about this type of "precision-bounded" approach. – Arets Paeglis Jun 11 '20 at 16:57