From: Wybo Dekker Date: 2005-12-14T00:01:23+09:00 Subject: Re: Using Float For Currency --693760-232907584-1134486071=:20851 Content-Type: MULTIPART/MIXED; BOUNDARY="693760-232907584-1134486071=:20851" This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --693760-232907584-1134486071=:20851 Content-Type: TEXT/PLAIN; charset=US-ASCII On Tue, 13 Dec 2005, Neil Stevens wrote: > Hunter's Lists wrote: > > Howdy, > > > > I have some methods that manipulate floats that represent a currency amount. > > > > I often end up with more precision than I need, i.e.: $9.756. > > > > What is the best way to scale that to 9.76? > > require 'bigdecimal' > > amount = BigDecimal.new('9.756') > rounded = (amount * 100).round / 100 > printf('%.02f', rounded) > > Outputs '9.76' There is at least one point more to make about rounding: this method has a bias when floats ending with a 5 are involved. In the extreme case, when all you three-decimal currency amounts end in a 5 (like $9.755, $9.765) then all are rounded upwards. Instead, half of them should be rounded up, the other half down. A good method to do that is to round to the nearest even digit: $9.755 -> $9.76 $9.765 -> $9.76 (not $9.77) The attached method round2 does this (although probably not very efficiently): 8.5.round2 -> 8 9.765.round2(0.01) -> 9.76 -- Wybo --693760-232907584-1134486071=:20851 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="round2.rb" Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: Content-Disposition: attachment; filename="round2.rb" PWJlZ2luIHJkb2MNCg0Kcm91bmQyIC0gdW5iaWFzZWQgcm91bmRpbmcgZm9y IGZsb2F0cw0KDQo9IERlc2NyaXB0aW9uDQoNCklkZWEgZnJvbTogDQogIEou IENoZW0uIEVkdWMuIDE5OTcgNzQgNDA1LiAgDQogIFJvdW5kaW5nIE51bWJl cnM6IFdoeSB0aGUgIk5ldyBTeXN0ZW0iIERvZXNuJ3QgV29yayANCiAgYnkg Vy4gUm9iZXJ0IE1pZGRlbiANCiAgQ2hlbWlzdHJ5IERlcGFydG1lbnQgDQog IEJvd2xpbmcgR3JlZW4gU3RhdGUgVW5pdmVyc2l0eSANCiAgQm93bGluZyBH cmVlbiwgT0ggNDM0MDMtMDIxMw0KDQpUaGlzIHBhcGVyIGV4cGxhaW5zIGEg Y29ycmVjdGlvbiB0byB0aGUgcm91bmRpbmcgcnVsZSBwcmV2aW91c2x5IHB1 Ymxpc2hlZA0KaW4gdGhpcyBKb3VybmFsLiBUaGUgZWFybGllciBhcnRpY2xl IHJlcG9ydGVkIHRoYXQgdGhlIGJlc3Qgd2F5IHRvIHJvdW5kDQpudW1iZXJz IGlzIHRvIGFsd2F5cyByb3VuZCB1cCB3aGVuIHRoZSBmaXJzdCBkaWdpdCBk cm9wcGVkIGlzIDUuIEhvd2V2ZXIsDQp0aGlzIHdpbGwgbGVhZCB0byBhY2N1 bXVsYXRpb24gb2YgZXJyb3Igd2hlbiBlcnJvcnMgYXJlIGF2ZXJhZ2VkLiBB DQpyb3VuZGluZyBzdHJhdGVneSB0aGF0IGxlYWRzIHRvIGxlc3MgZXJyb3Ig aXMgdG8gcm91bmQgdXAgd2hlbiA1IGlzDQpmb2xsb3dlZCBieSBhbnkgbm9u emVybyBkaWdpdHMsIGJ1dCB0byByb3VuZCBldmVuIHdoZW4gNSBpcyBmb2xs b3dlZCBieQ0KemVyb3Mgb3Igbm8gb3RoZXIgZGlnaXRzLiBCeSByb3VuZGlu ZyB0aGUgbGFzdCBrZXB0IGRpZ2l0IHRvIGFuIGV2ZW4NCm51bWJlciwgaGFs ZiB0aGUgdGltZSB0aGUgZGlnaXQgaXMgaW5jcmVhc2VkIGFuZCBoYWxmIHRo ZSB0aW1lIGl0IGlzIGtlcHQNCnRoZSBzYW1lIHNvIHRoYXQgZXJyb3JzIHRl bmQgdG8gY2FuY2VsIHdoZW4gYXZlcmFnZWQuDQoNCj1lbmQNCg0KY2xhc3Mg RmxvYXQNCg0KICAjIHJvdW5kMiBjYW4gYmUgY2FsbGVkIHdpdGggb3Igd2l0 aG91dCBhbiBhcmd1bWVudC4NCiAgIyBXaXRoIGFuIGFyZ3VtZW50IGNodW5r LCB0aGUgZmxvYXQgaXMgcm91bmRlZCB0byB0aGUgbmVhcmVzdCBtdWx0aXBs ZQ0KICAjIG9mIGNodW5rLiBXaXRob3V0IGFuIGFyZ3VtZW50LCBjaHVuayBk ZWZhdWx0cyB0byAxIHNvIHRoYXQgcm91bmRpbmcNCiAgIyBpcyB0byB0aGUg bmVhcmVzdCBpbnRlZ2VyLg0KICAjDQogICMgcm91bmQyIHdvcmtzIGxpa2Ug dGhlIHN0YW5kYXJkIEZsb2F0I3JvdW5kLCBleGNlcHQNCiAgIyB0aGF0LCB3 aGVuIHRoZSBsYXN0IGtlcHQgZGlnaXQgaXMgYSA1IGZvbGxvd2VkIGJ5IHpl cm9zIG9ubHksIGl0DQogICMgaXMgcm91bmRlZCB0byB0aGUgbmVhcmVzdCBl dmVuIGRpZ2l0OyB0aHVzOg0KICAjDQogICMgICA4LjUucm91bmQyIC0+IDgN CiAgIyAgIDcuNS5yb3VuZDIgLT4gOA0KICAjICAgOC4yNS5yb3VuZDIoMC4x KSAtPiA4LjIgKHJvdW5kZWQgZG93bikNCiAgIyAgIDcuNTUucm91bmQyKDAu MSkgLT4gNy42IChyb3VuZGVkIHVwKQ0KICAjDQogICMgX2ZsdF8ucm91bmQy KF9pbnRfPTEpIC0+IF9pbnRfDQogICMNCiAgIyBfZmx0Xy5yb3VuZDIoX2Zs dF8pIC0+IF9mbHRfDQoNCiAgZGVmIHJvdW5kMihjaHVuaz0xKQ0KICAgIGNh c2UgY2h1bmsNCiAgICB3aGVuIDENCiAgICAgIGlmIHNlbGYudG9fcyA9fiAv XC41JC8NCiAgICAgICAgcyA9IHNlbGYgPCAwID8gLTEgOiAxDQogICAgICAg IHggPSBzZWxmLmFicy50b19pDQogICAgICAgIHggKz0geCUyDQogICAgICAg IHggKiBzDQogICAgICBlbHNlDQogICAgICAgIHNlbGYucm91bmQNCiAgICAg IGVuZA0KICAgIGVsc2UNCiAgICAgIGNodW5rID4gMCBvciByYWlzZSBBcmd1 bWVudEVycm9yLCJGbG9hdC5yb3VuZDI6IGNodW5rIG11c3QgYmUgPiAwIg0K ICAgICAgKHNlbGYvY2h1bmspLnJvdW5kMipjaHVuaw0KICAgIGVuZA0KICBl bmQNCg0KZW5kDQoNCmlmIF9fRklMRV9fID09ICQwDQogIHB1dHMgIlJvdW5k aW5nOiINCiAgWyAyLCAxLCAwLjEsIDAuMyBdLmVhY2ggZG8gfGNodW5rfA0K ICAgIFsgMC41LCA3LjUsIDguNSwgNy4yNSwgNy41NSwgLTcuMjUsIC04LjU1 IF0uZWFjaCBkbyB8bnVtYmVyfA0KICAgICAgcHV0cyAiJTVzLnJvdW5kMigg JTNzICkgLT4gJTVzIiAlIFtudW1iZXIsIGNodW5rLCBudW1iZXIucm91bmQy KGNodW5rKV0NCiAgIGVuZA0KICBlbmQNCmVuZA0K --693760-232907584-1134486071=:20851-- --693760-232907584-1134486071=:20851--