All the answers add great information, but I would like to give a more direct answer.
Representing a currency (money)
The most suitable way is to use integers (int
or long
). The reason to avoid floating point numbers are binary representation problems that cause differences in values even in very simple operations.
In addition to Fowler (cited by Leonardo), Bloch also advocates the use of integers in the book Effective Java. Another source is this issue of SOEN.
The idea here is analogous to representing mass in grams rather than kilograms. In the case of Real, we represent the values in cents instead of real. So, the value R$ 10,99
(ten reais and ninety new cents) is represented by 1099
(one thousand ninety-nine cents).
Mathematical and financial operations
The operations of sum, subtraction and multiplication are carried out directly, without any difficulty. However, if there are splitting operations, the final result should be rounded appropriately to integer again.
Rounding is an interesting topic and we cannot be simplistic. The truth is that there is no fixed rule to round up or down. When we talk about money, we are not only considering precision, but who loses and who wins.
One example of legislation affecting rounding is the case of the Consumer Protection Code. The consumer charge should always be rounded down.
Another example used a lot in financial means is the distribution of plots. For example, suppose the calculation of plots of a loan R$ 100,70
three times without interest. In terms of legislation, the customer cannot pay more than the total amount to be charged. Note that the value divided into three parts is equal to 33,5666...
and we can’t round up (R$ 33,57
), otherwise the customer will pay the total of R$ 100,71
(a penny more). A solution to this is to round the parcel down (R$ 33,56
), resulting in a total of R$ 100,68
, and the company assumes the loss of 2 cents.
However, many financial institutions do not want these differences polluting accounting. We must remember that each round-off must be justified on an accounting basis. As a result, it is common in systems where I worked we have an adjustment in the last installment. Continuing with the example above, we would have the installments R$ 33,57
, R$ 33,57
and R$ 33,56
, totaling exactly R$ 100,70
.
Conversion between different currencies
The conversion from one currency to the other can follow the same concept of mathematical operations, only by adjusting the basic unit of media.
Presentation to the user
One of the advantages of using integers is separating the internal representation from the visual presentation.
The whole number can be easily formatted using any routine, with the of this SOEN response:
Number.prototype.formatMoney = function(c, d, t){
var n = this,
c = isNaN(c = Math.abs(c)) ? 2 : c,
d = d == undefined ? "." : d,
t = t == undefined ? "," : t,
s = n < 0 ? "-" : "",
i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
j = (j = i.length) > 3 ? j % 3 : 0;
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};
Note that the function must be adapted to extract the two decimal places of the number.
Considerations of the solution
Reliability
The results will always be correct and the solution behaves well in borderline cases, since there are no rounding problems. One should observe only the business rules of how and when round, as mentioned above.
Interoperability
This can be a complex point for any solution, as the number formatted in a input
HTML may not be correctly interpreted on the server.
Different technologies and frameworks validate and interpret data differently. The point is that if the numbers are formatted in the Submit, the server must extract all non-numeric characters and then convert the value to an integer number.
If the technology is not a limiting factor, the interoperability of this solution is excellent, even avoiding confusion with semicolons.
Robustness
Data entry robustness is not directly related to the representation form.
However, rationing by thinking of whole numbers can also help in this aspect. You know those systems (like at Atms), where you type the full value from right to left, always specifying the decimal part at the end? Like in this matter. It is possible to format with a plugin, as I did in this fiddle.
Presentation
Item already considered in previous topic. Any formatting routine works as long as you consider that the decimals are represented in the entire part of the number.
Efficiency
Even when there is a "native" type in the language, such as Decimal
or BigDecimal
, working with integers is more efficient from a computational point of view for obvious reasons.
Related: http://ux.stackexchange.com/questions/9105/international-currency-formatting-guidelines-currency-codes
– Sergio