The
Ultimate
Business Machine

Technology, business
and innovation.

And, not least, about
the Mac.

Weblog Archive Cutedge

by: Bernard Teo








Creative Commons License

Copyright © 2003-2012
Bernard Teo
Some Rights Reserved.

Wed 16 Aug 2006

Do the math ... or when is 156.14 != 156.14 ?

Category : Technology/maths.txt

This is a Cash Disbursement voucher in Luca :

I have a rule that says you can't save a voucher unless the debits and credits balance. So, here we have $156.14 being paid out of a checking account, recorded against an equal $156.14 in expenses. Yet the Save button refuses to be enabled. What is going on here?

Looking a bit closer at the objects :

NSLog(@"vouAmount = %f", [vouAmount doubleValue]);
NSLog(@"ttlAmount = %f", [ttlAmount doubleValue]);

we get :

Luca[1046] vouAmount = 156.140000
Luca[1046] ttlAmount = 156.140000

It's as we would expect but it remains puzzling, so we zoom even closer :

NSLog(@"vouAmount = %1.24f", [vouAmount doubleValue]);
NSLog(@"ttlAmount = %1.24f", [ttlAmount doubleValue]);

we get :

Luca[1046] vouAmount = 156.140000000000014779288904
Luca[1046] ttlAmount = 156.139999999999986357579473

The vouAmount is taken straight off the object. The total column has a rounding function applied to it, but still it's just one line item, for simplicity's sake. So both items are off the expected figure of 156.14. They never balance.

This happens only at certain values, not all the time. It happens because "real numbers" in digital computations are only a very close approximation to the mathematical concept of real numbers. The difference is infinitesimally small (my favourite expression in engineering school), but it's there all the same. It's what throws us off.

This reminds me of that paradox of Zeno, of a foot race between Achilles and a tortoise. The tortoise is given a headstart, but picture Brad Pitt as Achilles, huffing and puffing, always covering half the distance to the tortoise, always gaining, but never quite reaching, because the half-distance keeps getting smaller, and smaller, and smaller, but never disappears. It's become infinitesimally small.

The solution is to round both numbers before comparing them, even the one entered exactly as 156.14.. But we have to take care to do the rounding at lots of places, not just when the value is entered. For example, you do rounding when one value is multiplied by another. But what happens when you divide a dollar by three. You lose that last infinitesimally small fraction of a cent because computers work with discrete values, not a continuum.

So, that's why building such systems, mundane though they seem, is hard. It's a craft. It's precision work. But it's not the kind that will win Apple Design Awards at WWDC.

I'm fixing this in a Luca 2.2.2 release. But I have the rounding done all over the place. The art is to find a way to control this in just one spot in the application. What happens when I find a user whose currency system works with other than two decimal points? Is there such a thing?

Posted at 7:59AM UTC | permalink

Mac@Work
Put your Mac to Work

Sivasothi.com? Now how would you do something like that?

Weblogs. Download and start a weblog of your own.

A Mac Business Toolbox
A survey of the possibilities

A Business Scenario
How we could use Macs in businesses

VPN Enabler for Mavericks

MailServe for Mavericks

DNS Enabler for Mavericks

DNS Agent for Mavericks

WebMon for Mavericks

Luca for Mavericks

Liya for Mountain Lion & Mavericks

Postfix Enabler for Tiger and Panther

Sendmail Enabler for Jaguar

Services running on this server, a Mac Mini running Mac OS X 10.9.2 Mavericks:

  • Apache 2 Web Server
  • Postfix Mail Server
  • Dovecot IMAP Server
  • Fetchmail
  • SpamBayes Spam Filter
  • Procmail
  • BIND DNS Server
  • DNS Agent
  • WebDAV Server
  • VPN Server
  • PHP-based weblog
  • MySQL database
  • PostgreSQL database

all set up using MailServe, WebMon, DNS Enabler, DNS Agent, VPN Enabler, Liya and our SQL installers, all on Mavericks.