Skip to content
VLSI Mentor

Perl Part I · Module 2 · Variables, Scalars, and Data Types

Numbers: Integers, Floats and How Perl Stores Them

Perl does not make you choose between an integer type and a floating-point type. There is one kind of number, it holds whole values and decimals alike, and most of the time you can simply use it. This chapter covers the parts worth knowing anyway: how to write a long number so a reader can check it, what division actually returns, and one genuinely important limit. Perl will print 0.3 as the sum of 0.1 and 0.2 while storing something very slightly different — so the printed answer and the stored value are not always the same thing, and a comparison can fail on numbers that look identical.

Foundation12 min readPerlPart IFundamentalsNumbersPrecision

Part I · Module 2 · Chapter 2.4 · Numbers: Integers, Floats and How Perl Stores Them

1. One Numeric Kind

In many languages you choose a numeric type before storing a value — an integer here, a floating-point number there. Perl does not ask. A scalar holds a number, and the same scalar can hold 3 or 72.5:

Azvya Education Pvt. Ltd.VLSI Mentor
numbers.pl
use strict;
use warnings;

my $count   = 3;
my $average = 72.5;
my $cycles  = 1_000_000;

print "count:   $count\n";
print "average: $average\n";
print "cycles:  $cycles\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
count:   3
average: 72.5
cycles:  1000000

Three observations:

  • No type was declared, consistent with Chapter 2.2: my creates a name, not a type.
  • 72.5 needed no special treatment. A decimal is just a number.
  • 1_000_000 printed as 1000000. The underscores are a readability aid for whoever reads your source; Perl ignores them entirely. Use them on anything long enough to miscount — 1_000_000 cannot be misread as 100_000, and 1000000 can.

2. Division Returns a Decimal

One behaviour to settle early, because it differs from several other languages:

Azvya Education Pvt. Ltd.VLSI Mentor
division.pl
use strict;
use warnings;

print 1000 / 10, "\n";
print 10 / 4, "\n";
print int(10 / 4), "\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
100
2.5
2

10 / 4 is 2.5, not 2. Perl's / always performs the full division; it does not throw away the fractional part because both operands happened to be whole numbers. When you genuinely want a whole number, int() discards the fraction — note that it truncates toward zero rather than rounding, so int(2.9) is 2.

Also notice 1000 / 10 printed 100 rather than 100.0. Perl prints a number in the shortest form that represents it, so an integral result looks like an integer. That is a display decision, and the next section is about what happens when the display and the stored value disagree.

Operators in general — including %, ** and the compound forms — belong to Module 3. This chapter uses only what it needs.

3. The One Limit Worth Knowing

Decimal fractions are stored in binary, and most of them cannot be represented exactly — in the same way that one third cannot be written exactly in decimal, however many digits you allow. Perl's numbers are no exception.

Usually you never notice, because Perl prints the shortest representation:

Azvya Education Pvt. Ltd.VLSI Mentor
looks-fine.pl
use strict;
use warnings;

print 0.1 + 0.2, "\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
0.3

That looks like a complete answer. Ask for more digits and it is not:

Azvya Education Pvt. Ltd.VLSI Mentor
more-digits.pl
use strict;
use warnings;

printf "%.20f\n", 0.1 + 0.2;
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
0.30000000000000004441

The stored value is very slightly more than three tenths. printf with an explicit precision — Chapter 4.8 covers the formatting properly — simply stopped hiding it.

What print shows0.3
What is actually stored0.30000000000000004441…
Is it equal to 0.3?no

4. The Consequence

That last row is the part that matters. The following uses == to compare and ?: to pick one of two words — both belong to later chapters, and they appear here because asserting the result without demonstrating it would be a weaker lesson:

Azvya Education Pvt. Ltd.VLSI Mentor
not-equal.pl — ?: is borrowed from Chapter 8.4
use strict;
use warnings;

print 0.1 + 0.2 == 0.3 ? "equal\n" : "not equal\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
not equal

Two numbers that both display as 0.3 are not the same number. This is not a Perl defect — essentially every language that uses binary floating-point behaves identically, and it is a property of representing decimals in binary rather than of any one implementation.

5. Why This Matters in Engineering Work

Two reasons, and they are not symmetrical.

Most of the numbers in a flow script are whole and safe. Error counts, warning counts, seeds, test numbers, cycle counts — these are integers, they compare exactly, and nothing in §3 applies to them. It would be misleading to leave you nervous about arithmetic in general.

The numbers that are not whole are exactly the ones that get compared to thresholds. A timing slack of -0.043, a utilisation of 0.78, a clock period of 3.333. Those are measured decimals read out of a tool's report, and a script that asks whether a slack is exactly equal to a limit will eventually answer wrongly on a value that displays identically to the limit. The correct question is whether it is below the limit, or within a tolerance of it — which is a comparison, not an equality.

That is the whole engineering content of this chapter, and it costs one habit: thresholds are compared with < and >, never with ==. Part II relies on it when it starts reading real report values.

6. Common Mistakes

Expecting 10 / 4 to be 2. Perl returns 2.5. Use int() if you want truncation — and know that it truncates rather than rounds.

Expecting int() to round. int(2.9) is 2. Rounding is a different operation, and printf with a precision is the usual way to display a rounded value.

Testing a calculated decimal with ==. The symptom is a comparison that fails on values that print identically, which looks like a Perl bug and is not. §4 is the demonstration.

Reading the printed value as the stored value. print shows the shortest form. If you need to know what is really there, ask for digits with printf.

Putting commas in a long number. 1,000,000 is not a number in Perl. Underscores are the separator: 1_000_000.

7. What You Should Be Able to Say Now

  1. Perl has one numeric kind, used for whole numbers and decimals alike, and a scalar does not declare which it holds.
  2. Underscores in a numeric literal are ignored by Perl and exist for the reader.
  3. / returns the full result — 10 / 4 is 2.5 — and int() truncates toward zero rather than rounding.
  4. print shows the shortest representation, which can differ from the value actually stored.
  5. 0.1 + 0.2 prints 0.3 and is not equal to 0.3; this is binary floating-point, not a Perl defect.
  6. Whole numbers compare exactly; calculated decimals should be compared against a tolerance or with < and >.

8. Exercise

Exercise 1 — readable literals. Declare a scalar holding ten million using underscores, and print it. Confirm the underscores do not appear in the output, and say who they were for.

Exercise 2 — predict three divisions. Without running it, write down what each prints: print 9 / 3;, print 9 / 2;, print int(9 / 2);. Then run all three and account for any surprise.

Exercise 3 — expose the stored value. Using printf "%.20f\n", ..., print the stored value of 0.1 + 0.2 and of 0.5 + 0.25. One is inexact and one is exact. Say which, and offer an explanation for the difference based on §3.

Exercise 4 — reason about a threshold. A script must report a failure when a measured slack is below -0.040. A colleague writes a check for slack equal to -0.040 and reports that it "sometimes misses". Explain in two sentences what is going wrong and what the check should ask instead.

9. Summary

  • One numeric kind covers whole numbers and decimals; no type is declared.
  • Underscores make long literals readable and are invisible to Perl.
  • / gives the full result, so 10 / 4 is 2.5; int() truncates toward zero.
  • The printed value is the shortest representation, not necessarily the stored one.
  • 0.1 + 0.2 is not 0.3 — binary floating-point, shared by nearly every language.
  • Compare measured decimals with <, > or a tolerance, never ==. Whole numbers are unaffected.

Chapter 2.5 turns to the other common thing a scalar holds — text — and to the fact that everything read out of a file arrives as text whether it looks like a number or not.

Where this fits

Part of the Perl curriculum.