One, Two, Three, Four. I thought I understood the damn things. And then it turns outthey have ‘lifestyle choices’ and Mr. One says ‘you know, I just don’t FEEL like anInteger’ and suddenly they are making ‘changes’ and you’re alone with the Xbox, apound of bacon, and nothing but tears.
Floating Point Numbers
I’m talking numbers in Ruby right now, but I’m shaken to the core. Floating numbersare numbers! They should work right! They should ADD UP! Now, a floatingpoint number is at least equal to itself. This passes:
assert_equal(0.1, 0.1)
But this doesn’t:
assert_not_equal(0.1, 0.4-0.3)
You’d think 0.1 == 0.1 but you’d be wrong! You see, 0.1 is only an approximation ofthe value stored by the floating point system in binary. 0.3 is an approximation,and 0.4 is an approximation. And when they are mathed, they don’t approximate outequally. There’s a loss of precision. It’s pretty close. This passes:
expected_float = 0.1
actual_float = 0.4-0.3
assert ( (expected_float - actual_float).abs <= 0.00000005 )
…it’s just not exact. It’s wrong over in C# too.
[Test]
public void FloatTests()
{
Assert.AreEqual(0.1f, 0.3f - 0.2f);
}
Goes boom:
Modulus
What’s a modulus? First off, I thought it was the number you get when you use themod operator in a language…but it’s not. The modulus is actually the numberyou ‘divide’ by in a mod operation. The result is technically called the remainder.
Now the way I learned it, the mod operation is a lot like making change. If I have1453 copper pieces (cp) and one silver piece (sp) is 100 coppers, then I find outhow many silvers I have with simple division. This passes in C#:
int copper= 1453;
int silver= copper / 100;
int change= copper % 100;
Assert.AreEqual(14, silver);
Assert.AreEqual(53, change);
And in Ruby:
copper = 1453
silver = copper / 100
change = copper % 100
assert_equal 14, silver
assert_equal 53, change
It’s all good so far, right? But what if I owe money? What if my initial total is–1453 ? I owe 14 silvers and 53 coppers, right? Well, yes. And that’s what C# shows.–14 silver and –53 coppers. But not Ruby:
copper = -1453
silver = copper / 100
change = copper % 100
assert_equal -15, silver
assert_equal 47, change
You owe 15 silver. And when you pay…you’ll get 47 copper back. If you want the C#(C++, C, etc) results, you’ll need to use positive numbers and handle the negativeyourself.
I’ve been scratching my head around this, and it really seems like it’s an equallyvalid way of the numbers. The math people have both definitions lying around. Andsome cases have this method make more sense. Imagine you’re trying to find out whatO’Clock it is. You have your hours variable and you use the mod operator. HOURS %12. That works just fine, until you go negative. What if you wanted to know what O’Clockit was 143 hours ago? If it’s noon, and you’re using Ruby, –143 % 12 gives you theright answer.
I guess the accountants are right. “What do you want the numbers to be?”