Os dois maiores problemas envolvendo números de ponto flutuante são:
- unidades inconsistentes aplicadas aos cálculos (observe que isso também afeta a aritmética inteira da mesma maneira)
- falha em entender que os números FP são uma aproximação e como lidar de forma inteligente com o arredondamento.
O primeiro tipo de falha pode ser solucionado apenas fornecendo um tipo composto que inclui informações de valor e unidade. Por exemplo, um length
ou area
valor que incorpora a unidade (metros ou metros quadrados ou pés e pés quadrados, respectivamente). Caso contrário, você deve ser diligente em trabalhar sempre com um tipo de unidade de medida e somente converter em outro quando compartilharmos a resposta com um ser humano.
O segundo tipo de falha é uma falha conceitual. As falhas se manifestam quando as pessoas as consideram como números absolutos . Isso afeta operações de igualdade, erros cumulativos de arredondamento etc. Por exemplo, pode ser correto que, para um sistema, duas medições sejam equivalentes dentro de uma certa margem de erro. Ou seja, .999 e 1.001 são aproximadamente os mesmos que 1.0 quando você não se importa com diferenças menores que +/- .1. No entanto, nem todos os sistemas são tão brandos.
Se houver alguma facilidade no nível do idioma, eu chamaria isso de precisão da igualdade . Nas estruturas de teste NUnit, JUnit e de construção semelhante, é possível controlar a precisão considerada correta. Por exemplo:
Assert.That(.999, Is.EqualTo(1.001).Within(10).Percent);
// -- or --
Assert.That(.999, Is.EqualTo(1.001).Within(.1));
Se, por exemplo, C # ou Java foram alterados para incluir um operador de precisão, pode ser algo como isto:
if(.999 == 1.001 within .1) { /* do something */ }
No entanto, se você fornecer um recurso como esse, também deverá considerar o caso em que a igualdade é boa se os lados +/- não forem os mesmos. Por exemplo, + 1 / -10 consideraria dois números equivalentes se um deles estivesse dentro de 1 a mais ou 10 a menos que o primeiro número. Para lidar com esse caso, pode ser necessário adicionar uma range
palavra - chave:
if(.999 == 1.001 within range(.001, -.1)) { /* do something */ }