Subtracts the second number from the first and returns the difference.

1. Description

The sub operator pops two numbers from the operand stack, subtracts the top number (num2) from the second number (num1), and pushes the result back onto the stack. If both operands are integers and the result fits within the integer range, the result is an integer. Otherwise, the result is a real number.

This is a Level 1 operator, available in all PostScript implementations.

2. Syntax

num1 num2 sub difference

2.1. Stack Effect

Table 1. Before Execution
Position Content

Top

num2 (integer or real) - Subtrahend (number to subtract)

Top-1

num1 (integer or real) - Minuend (number to subtract from)

Table 2. After Execution
Position Content

Top

difference (integer or real) - Result of num1 - num2

3. Parameters

num1

The minuend - the number to subtract from (integer or real)

num2

The subtrahend - the number to subtract (integer or real)

4. Return Values

difference

The difference num1 - num2. Type depends on operands:

  • Integer if both operands are integers and result fits in integer range

  • Real otherwise

5. Examples

5.1. Basic Subtraction

% Integer subtraction
10 3 sub       % → 7 (integer result)

% Real subtraction
9.5 2.3 sub    % → 7.2 (real result)

% Mixed types
10 2.5 sub     % → 7.5 (real result)

% Negative results
5 10 sub       % → -5 (integer result)

5.2. Order Matters

% Subtraction is not commutative
10 3 sub       % → 7
3 10 sub       % → -7 (different result!)

% Stack order is crucial
5 2 sub        % Computes 5 - 2 = 3
2 5 sub        % Computes 2 - 5 = -3

5.3. Decrementing Values

% Decrement a counter
/counter 10 def
counter 1 sub
/counter exch def  % counter is now 9

% In a loop
/counter 10 def
{
    counter 0 gt {
        counter 1 sub /counter exch def
        % ... do something with counter ...
    } {
        exit
    } ifelse
} loop

5.4. Distance Calculation

% Calculate distance between points (1D)
/distance {  % x1 x2 -> dist
    sub abs
} def

10 3 distance   % → 7
3 10 distance   % → 7 (same distance)

6. Advanced Examples

6.1. Vector Subtraction

/subtractVectors {  % [x1 y1] [x2 y2] -> [x3 y3]
    % Subtract vector 2 from vector 1
    aload pop          % x2 y2
    3 -1 roll aload pop % y2 x2 x1 y1
    3 -1 roll exch     % y2 x1 y1 x2
    sub                % y2 x1 (y1-x2)
    3 1 roll           % (y1-x2) y2 x1
    exch sub           % (y1-x2) (x1-y2)
    exch               % (x1-y2) (y1-x2)
    2 array astore     % [x3 y3]
} def

[100 200] [30 50] subtractVectors  % → [70 150]

6.2. Range Checking

% Check if value is within range
/inRange {  % value min max -> bool
    % Returns true if min <= value <= max
    2 index             % value min max value
    2 index             % value min max value min
    ge                  % value min max (value>=min)
    3 1 roll            % (value>=min) value min max
    3 -1 roll           % (value>=min) min max value
    le                  % (value>=min) (value<=max)
    and                 % bool
} def

50 0 100 inRange  % → true
150 0 100 inRange % → false

6.3. Time Difference

% Calculate elapsed time
usertime               % Get start time
% ... do some work ...
usertime exch sub      % Calculate elapsed milliseconds
1000 div               % Convert to seconds

7. Edge Cases and Common Pitfalls

Order of operands is critical - sub is not commutative.

7.1. Operand Order

% WRONG: Operands in wrong order
% Want to compute x - 5
/x 10 def
5 x sub        % → -5 (computed 5 - 10)

% CORRECT: Proper order
/x 10 def
x 5 sub        % → 5 (computed 10 - 5)

7.2. Integer Underflow/Overflow

% Subtracting from minimum integer
-2147483648 1 sub   % → -2147483649.0 (becomes real)

% Large integer differences
2147483647 -1 sub   % → 2147483648.0 (becomes real)

7.3. Precision with Reals

% Real arithmetic may have precision issues
1.0 0.9 sub         % → 0.1 (may be 0.09999...)

% For precise decimal arithmetic, use integers
10 9 sub 10 div     % → 0.1 (exact)

8. Type Requirements

Both operands must be numeric (integer or real). Other types will cause a typecheck error:

% BAD: Non-numeric operands
(hello) 5 sub        % ERROR: typecheck
10 (world) sub       % ERROR: typecheck
[1 2] 3 sub          % ERROR: typecheck
  • add - Add two numbers

  • mul - Multiply two numbers

  • div - Divide two numbers (real result)

  • neg - Negate a number

  • abs - Absolute value

10. PostScript Level

Available in: PostScript Level 1 and higher

This is a fundamental arithmetic operator available in all PostScript implementations.

11. Error Conditions

stackunderflow

The operand stack contains fewer than two elements.

5 sub          % ERROR: stackunderflow (need 2 operands)
typecheck

One or both operands are not numbers.

(text) 5 sub   % ERROR: typecheck
undefinedresult

The result is outside the representable range for real numbers (extremely rare).

12. Performance Considerations

The sub operator is a primitive operation with O(1) constant time complexity. Performance is excellent and comparable to add.

13. Best Practices

  1. Remember operand order: The top of stack is subtracted FROM the second element

  2. Use integer arithmetic when possible for precision and performance

  3. Check for underflow/overflow in critical applications

  4. Be careful with real precision in financial or scientific calculations

13.1. Safe Subtraction with Bounds

% Subtract with minimum bound
/subWithMin {  % num1 num2 min -> result
    3 copy          % num1 num2 min num1 num2 min
    pop sub         % num1 num2 min (num1-num2)
    2 copy lt {     % If result < min
        exch pop    % Use min
    } {
        exch pop    % Use result
    } ifelse
} def

10 15 0 subWithMin  % → 0 (10-15=-5, but min is 0)

14. See Also


Back to top

Copyright © 2025 Ribose. PostScript is a trademark of Adobe. Distributed under the MIT License.