Árvore de páginas

O tipo numérico do AdvPL (ValType = "N") utiliza aritmética de ponto flutuante, e possui o limite máximo de 15 dígitos de precisão. 
Este limite considera todos os dígitos que compõe o número (contando da esquerda para a direita), independente da existência ou não do ponto decimal.

Caso seja necessário realizar operações aritméticas com precisão maior, utilize o tipo "F" – decimais de ponto fixo – descrito no link Decimais de Ponto Fixo -- 9661

Entendendo o limite de precisão em ponto flutuante e comportamentos do AdvPL

Uma variável numérica na aritmética de ponto flutuante, não garante um número fixo de casas decimais. Como a precisão garantida são 15 dígitos, quanto mais dígitos um número possuir na parte inteira, a quantidade de dígitos suportados na parte decimal é menor. Quando utilizamos o tipo decimal de ponto fixo, declaramos o tamanho do número ( escala ) e a precisão decimal, e a precisão declarada é garantida até o limite declarado do número. 

Por exemplo, vamos considerar o valor de PI com 11 casas decimais:

nPi := 3.14159265359 

A visualização do valor da variável nPI é limitada a 8 casas decimais. Logo, ao visualizar a variável no inspetor de variáveis do IDE / TDS ou mostrar ela na tela usando cValToChar() ou mesmo a função Str(), o valor mostrado será 3.14159265.

conout(nPi) // 3.14159265

Porém o valor em memória da variável continua sendo 3.14159265359, um número de 12 dígitos, com 1 dígito inteiro e 11 decimais. Se eu quiser converter este número para visualização, com todas as casas decimais, é preciso usar a função Transform(), por exemplo : 

conout( Transform(nPi,"9.99999999999") ) // agora sim é mostrado 3.14159265359

Agora, vamos considerar o seguinte número : 

nIntPi := 314159265359

Trata-se de um número inteiro de 12 dígitos, sem dígitos decimais. Agora, vamos somar estes dois números : 

nSomados := nPi + nIntPi 
conout(nSomados) // Será mostrado o número 314159265362.142 

Ao visualizar o número, somente foram mostradas 3 casas decimais, e o número resultante já tem 15 dígitos. O resultado exato da soma destes dois números é  314159265362.14159265359

Se tentarmos mostrar este número usando por exemplo a função transform, com todos estes dígitos ( 12 inteiros e 11 decimais ), será mostrado um número um pouco diferente : 314159265362.14202880859

Vamos colocar um abaixo do outro para ver as diferenças:

Resultado correto : 314159265362.14159265359
Resultado obtido : 314159265362.14202880859

Reparem que até a 3a casa decimal (15o digito), a parte decimal obtida no AdvPL ( .142 ) corresponde ao número original arredondado para cima na 3a casa decimal – pois da 4a casa decimal o valor é maior ou igual a 5. Como o número possui uma parte inteira de 12 dígitos, e a precisão máxima garantida são 15, o AdvPL garante a precisão do número até a 3a casa decimal. Agora, se eu tento mostrar o número forçando uma precisão decimal com mais de 3 dígitos, seja usando transform() ou mesmo STR(), o resultado já está arredondado do 3o decimal ( ou 15o digito do numero ), e os demais números já estão diferentes, pois com um número de 12 digitos na parte inteira, somente sobram 3 dígitos com precisão decimal garantida. Logo, se for necessária uma precisão decimal de 8 dígitos, a parte inteira do número não pode ter mais de 7 dígitos – pois o total suportado são 15.

Esta é a diferença entre o ponto flutuante e um número decimal de ponto fixo : Um número em ponto flutuante tem precisão fixa de número de dígitos, onde a precisão decimal é afetada pela quantidade de dígitos inteiros usados no número. Já com a utilização de uma aritmética de ponto fixo, podemos definir o tamanho total do número em dígitos ( ou escala ), e uma quantidade de dígitos para a precisão decimal, e essa precisão é sempre obtida, independente da quantidade de dígitos da parte inteira usada no número.



  • Sem rótulos