RESUMO:
double roundit(double num, double N)
{
double d = log10(num);
double power;
if (num > 0)
{
d = ceil(d);
power = -(d-N);
}
else
{
d = floor(d);
power = -(d-N);
}
return (int)(num * pow(10.0, power) + 0.5) * pow(10.0, -power);
}
Portanto, você precisa encontrar a casa decimal do primeiro dígito diferente de zero, salvar os próximos N-1 dígitos e arredondar o enésimo dígito com base no resto.
Podemos usar o log para fazer o primeiro.
log 1239451 = 6.09
log 12.1257 = 1.08
log 0.0681 = -1.16
Portanto, para números> 0, calcule o teto do log. Para números <0, tome o chão do log.
Agora temos o dígito d
: 7 no primeiro caso, 2 no segundo, -2 no terceiro.
Temos que arredondar o (d-N)
décimo dígito. Algo como:
double roundedrest = num * pow(10, -(d-N));
pow(1239451, -4) = 123.9451
pow(12.1257, 1) = 121.257
pow(0.0681, 4) = 681
Em seguida, faça o arredondamento padrão:
roundedrest = (int)(roundedrest + 0.5);
E desfaça o pow.
roundednum = pow(roundedrest, -(power))
Onde a potência é a potência calculada acima.
Sobre a precisão: a resposta da pirólise está de fato mais próxima do resultado real. Mas observe que você não pode representar 12,1 exatamente em qualquer caso. Se você imprimir as respostas da seguinte forma:
System.out.println(new BigDecimal(n));
As respostas são:
Pyro's: 12.0999999999999996447286321199499070644378662109375
Mine: 12.10000000000000142108547152020037174224853515625
Printing 12.1 directly: 12.0999999999999996447286321199499070644378662109375
Então, use a resposta do Pyro!