Bom dia, pessoa!
Estou com um problema referente a cálculos usando float.
Estou trabalhando em um dispositivo que possui uma plataforma específica, com um SDK específico (e isso é bem ruim) e, apesar de muitas funções serem as mesmas do C padrão, algumas não funcionam exatamente igual as do C padrão (e isso é mais ruim ainda), que é o caso da função "sprintf(...)".
Preciso transforma uma variável float em uma string. Eu sei que a função "sprintf(...)" faz isso, porém, essa função não está funcionando para esse tipo de conversão, é um problema da plataforma mesmo, mas ela funciona bem para transformar um valor inteiro em uma string.
Bom... então, eu criei uma função que separa a parte inteira da parte decimal, converto a parte decimal em inteira e depois uso a função "sprintf(...)" para juntar as partes, colocar um ponto entre elas e armazenar em um buffer, logo, eu tenho o valor de float convertido para string.
Ex:
1 - Valor original: 12.5301f
2 - Parte inteira: 12
3 - Parte decimal: 0.5301f -> converte para inteiro: 5301
4 - uso o "sprintf ()" para concatenar as partes e converter para string: sprintf(buf, "%d.%d, 12, 5301);
5 - conteúdo do "buf" = "12.5301";
Até ai ok.
Para eu converter a parte decimal em inteiro eu fiz da seguinte forma:
1 - Multiplico a parte decimal por 10, para que a primeira casa decimal vire um valor inteiro;
2 - Armazeno e acumulo a parte inteira;
3 - desconto a parte inteira da parte decimal (deixando, novamente, apenas a parte decimal na variável) até que a variável tenha o valor "0.0";
Ex:
Decimal = 0.530100 * 10 = 5.301000 -> Decimal = 0.301000 Inteiro = 5
Decimal = 0.301000 * 10 = 3.010000 -> Decimal = 0.010000 Inteiro = 53
Decimal = 0.010000 * 10 = 0.100000 -> Decimal = 0.100000 Inteiro = 530
Decimal = 0.100000 * 10 = 1.000000 -> Decimal = 0.000000 Inteiro = 5301
Fim -> Inteiro = 5301
Só que isso não está funcionando, pois, sempre que multiplico o valor decimal por 10, o valor decimal está se alterando de uma forma imprevista.
Então resolvi fazer um teste no windows.
Usando o netbens como IDE eu implementei a mesma função e vi que ocorre o mesmo problema .
O problema é que, quando eu multiplico a parte decimal por 10, o processador está "desaredondando" o valor decimal. Veja abaixo o mesmo processo anterior, mas agora o que ocorre realmente, no windows:
Decimal = 0.530100 * 10 = 5.300998 -> Decimal = 0.300998 Inteiro = 5
Decimal = 0.300998 * 10 = 3.009987 -> Decimal = 0.009987 Inteiro = 53
Decimal = 0.009987 * 10 = 0. 099869 -> Decimal = 0. 099869 Inteiro = 530
Decimal = 0. 099869 * 10 = 0. 998688 -> Decimal = 0. 998688 Inteiro = 5300...
... E assim vai até que chegue em algum ponto onde "Decimal = 0.0". E isso vai bastante longe a ponto de dar overflow na variável inteiro deixando o resultado com um valor não esperado tipo: Inteiro = -232161348412479...
Minha duvida é:
1) Porque o processador "desaredonda" o valor decimal quando multiplico por 10?
2) Isso é um comportamento normal?
3) Eu estou fazendo algo errado?
4) Não estou levando em consideração algum comportamento de hardware ou SO?
Estou enviando o código para vocês testarem. Nó código existem alguns "prints" para ver os valores conforme for calculando a transformação. Fiquem a vontade para mudarem os "prints" de lugar, mas só peço que fiquem atentos a dois "prints" que destaquei, no código, e quando impressos apresentam setas apontando para valor "printado", são esses "prints" que mostram o momento do "desaredondamento".
Agradeço desde já pela a ajuda.
TesteFloat.c