Alterar temporariamente os modos de arredondamento não é tão incomum e é possível com bin/printf
, embora não seja per se que você precise alterar as fontes.
Você precisa das fontes dos coreutils, eu usei a versão mais recente disponível hoje, que era link .
Descompacte em um diretório de sua escolha com
tar xJfv coreutils-8.24.tar.xz
Mude para o diretório de origem
cd coreutils-8.24
Carregue o arquivo src/printf.c
no editor de sua escolha e troque a função main
inteira com a seguinte função, incluindo as duas diretivas de pré-processador, para incluir os arquivos de cabeçalho math.h
e fenv.h
. A função principal está no final e começa em int main...
e termina no final do arquivo com o colchete de fechamento }
#include <math.h>
#include <fenv.h>
int
main (int argc, char **argv)
{
char *format;
char *rounding_env;
int args_used;
int rounding_mode;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
atexit (close_stdout);
exit_status = EXIT_SUCCESS;
posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
// accept rounding modes from an environment variable
if ((rounding_env = getenv ("BIN_PRINTF_ROUNDING_MODE")) != NULL)
{
rounding_mode = atoi(rounding_env);
switch (rounding_mode)
{
case 0:
if (fesetround(FE_TOWARDZERO) != 0)
{
error (0, 0, _("setting rounding mode to roundTowardZero failed"));
return EXIT_FAILURE;
}
break;
case 1:
if (fesetround(FE_TONEAREST) != 0)
{
error (0, 0, _("setting rounding mode to roundTiesToEven failed"));
return EXIT_FAILURE;
}
break;
case 2:
if (fesetround(FE_UPWARD) != 0)
{
error (0, 0, _("setting rounding mode to roundTowardPositive failed"));
return EXIT_FAILURE;
}
break;
case 3:
if (fesetround(FE_DOWNWARD) != 0)
{
error (0, 0, _("setting rounding mode to roundTowardNegative failed"));
return EXIT_FAILURE;
}
break;
default:
error (0, 0, _("setting rounding mode failed for unknown reason"));
return EXIT_FAILURE;
}
}
/* We directly parse options, rather than use parse_long_options, in
order to avoid accepting abbreviations. */
if (argc == 2)
{
if (STREQ (argv[1], "--help"))
usage (EXIT_SUCCESS);
if (STREQ (argv[1], "--version"))
{
version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
(char *) NULL);
return EXIT_SUCCESS;
}
}
/* The above handles --help and --version.
Since there is no other invocation of getopt, handle '--' here. */
if (1 < argc && STREQ (argv[1], "--"))
{
--argc;
++argv;
}
if (argc <= 1)
{
error (0, 0, _("missing operand"));
usage (EXIT_FAILURE);
}
format = argv[1];
argc -= 2;
argv += 2;
do
{
args_used = print_formatted (format, argc, argv);
argc -= args_used;
argv += args_used;
}
while (args_used > 0 && argc > 0);
if (argc > 0)
error (0, 0,
_("warning: ignoring excess arguments, starting with %s"),
quote (argv[0]));
return exit_status;
}
Execute ./configure
da seguinte forma
LIBS=-lm ./configure --program-suffix=-own
Ele coloca o sufixo -own
em cada subprograma (há muito) apenas no caso de você querer instalá-los todos e não tiver certeza se eles se encaixam com o resto do sistema. Os coreutils não são nomeados utilitários core sem um motivo!
Mas o mais importante é o LIBS=-lm
na frente da linha. Precisamos da biblioteca matemática e esse comando informa ./configure
para incluí-la na lista de bibliotecas necessárias.
Executar make
make
Se você tiver um sistema multicore / multiprocessador, tente
make -j4
onde o número (aqui "4") deve representar o número de núcleos que você está disposto a poupar para esse trabalho.
Se tudo correu bem, você tem o novo printf
int src/printf
. Experimente:
BIN_PRINTF_ROUNDING_MODE=1 ./src/printf '%.0f\n' 196.5
BIN_PRINTF_ROUNDING_MODE=2 ./src/printf '%.0f\n' 196.5
Ambos os comandos devem diferir na saída. Os números após IN_PRINTF_ROUNDING_MODE
significam:
-
0 Arredondamento para 0
-
1 Arredondamento para o número mais próximo (padrão)
-
2 Arredondamento em direção ao infinito positivo
-
3 Arredondamento em direção ao infinito negativo
Você pode instalar o todo (não recomendado) ou apenas copiar o arquivo (renomear antes é altamente recomendado!) src/printf
em um diretório no seu PATH
e usar como descrito acima.