use BigDecimal for precision