A ver, precisión vas a perder seguro, por que calculando numeros de coma flotante en una computadora acabas perdiendo precisión. Lo que ocurre es que con BigDecimal y BigInteger puedes controlar hasta donde controlas la precisión y con las primitivas no.
De todas formas, tambien tienes que tener en cuenta el orden de las operaciones. Por ejemplo, * y / son transitivos pero...
Cita: float resultado = (-10f / 3f) + (5f * 2f / 3f); -> da 0
float resultado = (-10f / 3f) + (5f * (2f / 3f)); -> da 2.3841858E-7
Por que la division introduce perdida de precisión y si multiplicas despues, multiplicas esa perdida de precisión y la haces más grande.
Con BigDecimal, lo mismo:
Cita: MathContext mc = new MathContext(6); // Precision para los calculos
BigDecimal first = new BigDecimal(-10).divide(new BigDecimal(3), mc);
BigDecimal second = new BigDecimal(5).multiply(new BigDecimal(2).divide(new BigDecimal(3), mc));
first = first.add(second); -> first es 0.000005
pero si usas
Cita: BigDecimal second = new BigDecimal(5).multiply(new BigDecimal(2)).divide(new BigDecimal(3), mc);
entonces first te devolvera 0.000000
Con BigDecimal puedes decir que quieres precision hasta x digitos y luego redondeas si hace falta. Con las primitivas no sabes que precision tienes, asi que a la hora de redondear, pues no estas seguro cuanto has podido perder.
S!