-2

When I run the following Perl one-liner:

$ perl -e 'print "Oh no!\n" unless 1835 == 100*18.35'

I get

Oh no!

Why is that?

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
Tom
  • 4,666
  • 2
  • 29
  • 48
  • You missed code formatting. :( – toreau May 04 '17 at 14:10
  • @toreau I've improved formatting – Tom May 04 '17 at 14:11
  • 2
    Using a pencil and paper write down the *decimal* representation of 1/3rd. Multiply it by 3. Tell us the answer. If you wrote down 0.3333 your answer will be 0.9999. In programming a floating point number is often stored using a binary representation, much like this example just used of representing 1/3rd as 0.3333. That's what you missed. – DavidO May 04 '17 at 14:21
  • 1
    You missed several things, including, but not limited to the fact that your question is not about string comparisons at all, but you gave your post a misleading title. And, the fact that you added weird complications to make the problem statement as opaque as possible. – Sinan Ünür May 04 '17 at 14:33

1 Answers1

7

What you're missing is an old computer science problem - floating point conversion.

You see, you cannot precisely represent '0.35' as a floating point number since it's a periodic number in binary.

So if you add:

my $new = $a->{a} - $b;
print $new;

You'll get:

2.27373675443232e-013

$a->{a} is very slightly more than $b and thus the test is correct.

You can see this at work if you:

my $new_val = 18.35 - 18;
print $new_val;

Whilst we're at it though - don't use $a or $b - they're reserved for sort. And single letter var names aren't good style anyway.

Also my $a = {}; is redundant - there's no need to initialise an empty hash-reference like that.

To do what you want, then you either need to compare 'like types' or cast explicitly to integer:

$a->{a} = int(18.35 * 100);
ikegami
  • 367,544
  • 15
  • 269
  • 518
Sobrique
  • 52,974
  • 7
  • 60
  • 101