Não use os tipos _DecimalNN!

As especificações IEEE 754:2008 e ISO 9899:1999 e superiores oferecem tipos de representação de ponto flutuante em decimal: _Decimal32, _Decimal64 e _Decimal128. Parece uma boa ideia usá-los para evitar alguns problemas de conversão de bases numéricas (decimal → binário, e vice-versa), mas existem vários problemas.

O primeiro é que, embora esses sejam tipos reconhecidos pelo compilador, na verdade são estruturas (struct) e a conversão dos tipos binários (float, double …) não pode ser feita por casting e não há promoções automáticas. Ou seja, a função abaixo não compila:

_Decimal32 dfadd(_Decimal32 x, float y)
{ return x + y; }

Você tem que, explícitamente usar um assinalamento para fazer a conversão, assim:

_Decimal32 dfadd(_Decimal32 x, float y)
{ 
  _Decimal32 temp = y;
  return x + temp; 
}

Outro problema é que não há suporte, por parte do processador, para essa codificação de ponto flutuante em decimal. A função acima, quando compilada, gera algo assim:

  global dfadd
dfadd:
  sub  rsp,24
  movd dword [rsp+12],xmm0
  call __bid_addsd3
  movd dword [rsp+12],xmm0
  add  rsp,24
  ret

Essa estrutura de código, onde o resultado é colocado na pilha, é tipicamente usado em funções que retornam estruturas.

Compare com o código usando float:

; float _fadd(float x, float y)
; { return x + y; }
  global _fadd
_fadd:
  addss xmm0, xmm1
  ret

Ainda outro problema é que a libc não oferece qualquer suporte aos tipos de ponto flutuante decimais. A função printf, por exemplo, não os reconhece, a não ser que você tenha um “plugin” instalado na libc (e deve recompilá-la para isso!).

Então, não fique tentado a usar os tipos _DecimalNN. Eles são menos precisos que os tipos padrão, as operações que os envolvem são mais lentas e o suporte das bibliotecas é pouco ou nulo…

Anúncios