Conversões Numéricas Utilizando std::ratio

por Fabio A. Mazzarino

Uma boa funcionalidade adicionada no C++11, a biblioteca std::ratio cria meios para expressar diferentes tipos de relação entre grandezas, facilitando a aritmética básica e a conversão entre elas, além de trazer um conjunto de instâncias padrão para facilitar as conversões mais básicas.

A classe é bem mais simples que parece, simplesmente armazena a relação entre grandezas através de um numerador, e um denominador, sempre valores inteiros. Assim podemos declarar dois ratios de exemplo:

typedef std::ratio<1, 1> meter;
typedef std::ratio<1, 1000> kilometer;
typedef std::ratio<1, 1> real;
typedef std::ratio<10, 52> dollar;

Note que para a conversão do dólar foi preciso multiplicar o valor por 10, assim 1:5,2 virou 10:52.

A biblioteca ratio inclui um conjunto de ratios pré-definidos que podem ser muito úteis:

TIPODEFINIÇÃOPOTÊNCIA DE 10
yoctoratio<1, 1000000000000000000000000>-24
zeptoratio<1, 1000000000000000000000>-21
attoratio<1, 1000000000000000000>-18
femtoratio<1, 1000000000000000>-15
picoratio<1, 1000000000000>-12
nanoratio<1, 1000000000>-9
microratio<1, 1000000>-6
milliratio<1, 1000>-3
centiratio<1, 100>-2
deciratio<1, 10>-1
decaratio<10, 1>1
hectoratio<100, 1>2
kiloratio<1000, 1>3
megaratio<1000000, 1>6
gigaratio<1000000000, 1>9
teraratio<1000000000000, 1>12
petaratio<1000000000000000, 1>15
exaratio<1000000000000000000, 1>18
zetaratio<1000000000000000000000, 1>21
yottaratio<1000000000000000000000000, 1>24
Instâncias de ratio pré-definidas

Para efetuar uma conversão é simples:

double dist_meters = 550;
double dist_kilometers = (std::kilo::num / std::kilo::den) *  dist_meters;

Ou ainda, convertendo real para dólares:

double myreal = 1000.00;
double mydollar = myreal * dollar::num / dollar::den;
std::cout << "Total dollars: US$ " << mydollar << std::endl;

É possível utilizar aritmética de ratios com as funções:

  • std::ratio_add
  • std::ratio_subtract
  • std::ratio_multiply
  • std::ratio_divide

E comparação entre ratios com as funções:

  • ratio_equal
  • ratio_not_equal
  • ratio_less
  • ratio_less_equal
  • ratio_greater
  • ratio_greater_equal

Esse assunto parece até simples demais, e na verdade é simples mesmo. Esses tipos e funções foram criados para serem utilizados no namespace std::chrono, que será o post da próxima quinta-feira.