I don’t know what a number is anymore!
One, Two, Three, Four. I thought I understood the damn things. And then it turns out they have ‘lifestyle choices’ and Mr. One says ‘you know, I just don’t FEEL like an Integer’ and suddenly they are making ‘changes’ and you’re alone with the Xbox, a pound 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 numbers are numbers! They should work right! They should ADD UP! Now, a floating point 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 of the 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 out equally. 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 the mod operator in a language…but it’s not. The modulus is actually the number you ‘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 have 1453 copper pieces (cp) and one silver piece (sp) is 100 coppers, then I find out how 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 negative yourself.
I’ve been scratching my head around this, and it really seems like it’s an equally valid way of the numbers. The math people have both definitions lying around. And some cases have this method make more sense. Imagine you’re trying to find out what O’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’Clock it was 143 hours ago? If it’s noon, and you’re using Ruby, –143 % 12 gives you the right answer.
I guess the accountants are right. “What do you want the numbers to be?”