Problem response
From what I understand, you want to format an "integer that internally has two decimals" as a monetary value. You handled money, the answer necessarily goes through Bigdecimal.
private static String formataPtBr(int inteiro)
{
BigDecimal hundred = BigDecimal.TEN.pow(2);
BigDecimal value = BigDecimal.valueOf(inteiro).divide(hundred);
NumberFormat nf = NumberFormat.getCurrencyInstance(new Locale("pt",
"BR"));
String formatado = nf.format(value);
// System.out.println(formatado);
return formatado;
}
Six things:
You can do it in other ways, with int
, string
? Yeah, but then it opens up unexpected rounding and trucking problems. It will work in 99.99999% of cases, but with 99.99999% certainty it will cost you whole nights badly slept, hunting these heisenbugs. None of the solutions presented mention fpstrict
, so there is zero guarantee that the result you see on your machine is what will be calculated on another.
Name: format_data? Best something much more specific, camelCase: formataBrl()
, formataPtBr()
or something like that. It matches more with the content of the function.
Using a primitive type for something very specific and different from the original is a code Smell. Maybe I’ll find a Overkill create a specific type for number, but if you are making a large and serious system, this is a decision that you going repent.
Related to the previous, you are doing x = formata_data(valor)
instead of x = valor.formataPtBr(2)
. Another sign that things are poorly structured.
Having a specific type will force you to use the always correct type and that’s good. Will avoid to pass the whole unintentionally in a place that accepts whole, at the time of debugging you will always see the correct formatted result, without mental juggling.
If you’re worried about performance, create singletons of hundred
and nf
. Where to put? All the more reason to create a specific class for this kind of money which is an "integer with two decimal places".
Bigdecimal is ready, is standard, well tested and covers all the above points.
Whole for coins virtual
There is a situation in which the use of integer for coins is acceptable. The case of virtual coins, fake. I’m talking here about scores, digital games money, stuff like that. In this kind of context, where there’s a lot of non-decimal fractionation this could be interesting.
For example, in a virtual world where the smallest denomination is copper, which is equivalent to 100 silvers, which in turn is equivalent to 100 golds, it is interesting to keep the money balance in the smallest denomination (copper), as this facilitates all accounts. Only at the time of showing that, then yes, it makes itself the separation of the factors in a way "for humans", leaving the whole shape for the machine to deal.
Out of that context is a bad idea.
Decimal for coins real
'Cause the whole thing is a good idea for pretend coins, and a bad idea for real coins? In a nutshell: division, multiplication, exponentiation, square root, rounding.
Fake coins usually only operate sums, subtractions, multiplications. Real coins are quickly wrapped in operations financial, involving higher mathematics, which demand decimal extras, partial to function properly. This is impossible in a "no scale" type, as is the case of using fixed integer with two decimal places.
And these are the most "simple" operations. And if you’re having trouble putting decimals in the representation, it doesn’t look like you’re going to even hit those other algorithms. Performance, then, forget it.
Catch something simple, round up. It has five hundred types of rounding, all different from each other, and which exist because they are necessary in certain types of formula. An integer type with two decimals nor has to round up in addition to the two decimal places, from which it is deduced that such a type will not even function in these formulas.
So, seriously. If you’re dealing with real money, use Bigdecimal.
If you don’t want to use Bigdecimal, at least create a "Mymoney" type, to differentiate this case from others, and hang appropriate methods on it, instead of loose functions in the code.
Living and learning, for me it was absurd to treat currency as a whole. Now everything makes more sense.
– Rubico
It’s absurd to treat currency for real as a whole, see my answer. To keep, present or preserve finite precision numbers
float
s anddoubles
s are not appropriate, but this does not imply that the best answer is whole. It has memory and database types specific to finite precision numbers. They must be used.– André LFS Bacci
@Andrélfsbacci anguns of the most knowledgeable on the subject disagree with you. Anyway I didn’t say what’s best, I said it’s a better situation than
float
. But I am far from saying that this is absurd. That would be absurd. Several softwares are made like this by very competitive people for a long time. The fact that you do not like the solution does not mean that it is not effective. You can choose whatever you want for yourself but don’t impose your taste on everyone.– Maniero