Rounding in the price db.

John Ralls jralls at ceridwen.us
Fri Aug 28 03:55:53 EDT 2015


I’ve pushed a feature branch, single-price, to my Github repo (https://github.com/jralls/gnucash) which covers most of what we’ve discussed here. I’m still wrestling with the math of how to sensibly handle rounding itself, so what’s there still uses the hard-coded 10^6 denom. The branch is from maint because I’d like to put these changes in 2.6.8.

The actual changes are explained in the commit notes. In my limited testing it appears to work and to provide stability when doing multiple transactions with the same exchange rate. Please test some more; I’m sure I didn’t think of every possible variation.

As for the math, here’s the conundrum: I proposed earlier to base the rounding on what would make a 1 scu change in the “to” commodity. The problems with that idea are that it depends entirely on the amount in the “from” commodity and that prices are often quoted in fractions of a scu. For example, the Wall Street Journal website quotes the Yen at 120.98 to the USD. The Yen’s scu is 1, and the change in the rate to make a 1¥ change in the value is different if the USD amount is $10 from what it would be if the amount was $1000. Carry that to its illogical conclusion and we need infinite precision, and that’s ignoring the fact that we need infinite precision to exactly represent a lot of rational fractions, but since all the real money systems use decimal math nowadays that’s not really germane.

So I have a new proposal: If the commodities are both currencies, store exchange rates in the direction where the rate > 1, set the denominator to 1000, and round-half-up. The price retrieval code already checks in both directions. If only one of the commodities is a currency then it’s a price and we store it in the currency with the denominator = the currency’s scu * 10000.

That leaves commodity-commodity prices. The most common example in modern life is stock-for-stock exchanges resulting from mergers or spin-offs. These tend to be one-offs, so no rounding required. Barter exchange, where one exchanges one commodity for another (e.g. two bushels of corn for a cow), is similarly fractional rather than decimal, so again not rounding is appropriate. The third case is the problem: Bitcoin and similar pseudo-currencies. For maint I think we’re going to have to leave those prices unrounded as well, but perhaps for master we should consider creating a separate commodity category so that users can create commodities that GnuCash treats as currencies.

Regards,
John Ralls




More information about the gnucash-devel mailing list