Difference between revisions of "Minus"

From Lazarus wiki
Jump to navigationJump to search
 
(10 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 +
{{Minus}}
 +
 +
<div style="float:right; margin: 0 10px 10px 0; padding:40px; font-size:500%; font-family: Georgia; background-color: #f9f9f9; border: 2px solid #777777;">-</div>
 +
 +
In [[ASCII]], the character code decimal <syntaxhighlight lang="pascal" inline>45</syntaxhighlight>
 +
(or [[Hexadecimal|hexadecimal]] <syntaxhighlight lang="pascal" inline>2D</syntaxhighlight>) is defined to be
 +
<syntaxhighlight lang="pascal" inline>-</syntaxhighlight> (hyphen-minus).
 +
 +
== Occurrences ==
 +
 +
The symbol <syntaxhighlight lang="pascal" inline>-</syntaxhighlight> (pronounced “minus”) is used to
 +
* indicate the negative sign of a number literal
 +
* subtract two numbers (using infix notation)
 +
* form the difference of two [[Set|sets]].
 +
 +
<syntaxhighlight lang="pascal">
 +
program minusDemo(input, output, stderr);
 +
 +
var
 +
x: longint;
 +
g: longint;
 +
m: set of (foo, bar);
 +
 +
begin
 +
// unary operator: negative sign
 +
x := -42;                    // x becomes negative 42
 +
 +
// binary operator: difference of numbers
 +
g := 144 - 169;              // g becomes negative 25
 +
 +
// binary operator: difference of sets
 +
m := [foo, bar] - [bar];      // m becomes {foo}
 +
end.
 +
</syntaxhighlight>
 +
 +
Minus is also a unary operator.
 +
You can write such stupid expressions as <syntaxhighlight lang="pascal" inline>----+--+--+--8</syntaxhighlight>.
 +
 +
== Operation with numbers ==
 +
 +
Beware:
 +
The result's target of subtractions (and sign inversions) should be a ''signed'' integer.
 +
If it's not, with [[sRangechecks|<syntaxhighlight lang="pascal" inline>{$rangechecks}</syntaxhighlight>]] [[Compiler directive|directive]] enabled, it will possibly cause a [[runtime error|run-time error]].
 +
In any other case an arithmetically wrong result is produced.
 +
<syntaxhighlight lang="pascal">
 +
program faultySubtraction(input, output, stderr);
 +
 +
var
 +
x, y: longword;
 +
 +
begin
 +
y := 1;
 +
{$push}
 +
{$rangechecks off} // otherwise the next expression
 +
x := 0 - y;        // yields RTE 201
 +
{$pop}
 +
 +
writeLn(x);
 +
end.
 +
</syntaxhighlight>
 +
 +
This program prints <syntaxhighlight lang="pascal" inline>4294967295</syntaxhighlight>, which equals to <syntaxhighlight lang="pascal" inline>high(longword)</syntaxhighlight> because of the (unsigned) integer overflow.
 +
 +
However note, there are situations where negative signs do not necessarily provoke an error.
 +
Attempting to store a “negative” zero won't harm:
 +
 +
<syntaxhighlight lang="pascal" line>
 +
program minusOperations(input, output, stderr);
  
{{Minus}}
+
{$rangeChecks on}
 +
 
 +
var
 +
n: longword;
 +
 
 +
begin
 +
// "negative" zero equals to (sign-less) zero
 +
n := 0;
 +
n := -n;
 +
</syntaxhighlight>
 +
 
 +
Also note, arithmetic integer operations are done with the processor's native integer type.
 +
Although intermediate results fall out of range, the code generated by <syntaxhighlight lang="pascal" inline>{$rangechecks on}</syntaxhighlight> ensures the type's boundaries aren't exceeded ''after'' the result's already stored.
 +
<syntaxhighlight lang="pascal" line start="13">
 +
// intermediate results can be out of range:
 +
n := 1;
 +
n := n - n - n + 1;
 +
end.
 +
</syntaxhighlight>
  
<div style="float:left; margin: 0 10px 10px 0; padding:40px; font-size:500%; font-family: Georgia; background-color: #f9f9f9; border: 2px solid #777777;">-</div>
+
This whole program will finish with an {{Doc|package=RTL|unit=system|identifier=exitcode|text=<syntaxhighlight lang="pascal" inline>exitCode</syntaxhighlight>}} of zero (that means “successful” [actual value might vary among platforms]).
  
 +
In consequence of the latter mentioned behavior:
 +
Integer overflows in the processor's native type can not be caught (in that way).
 +
In [[Assembly language|assembler]] you would have access evaluating several status flags, but in [[Pascal]] you do not.
 +
Instead you can use [[sOverflowchecks|<syntaxhighlight lang="pascal" inline>{$overflowChecks}</syntaxhighlight>]] which will evoke a run-time error.
  
 +
<syntaxhighlight lang="pascal" line highlight="3,10">
 +
program overflowChecksDemo(input, output, stderr);
  
 +
{$overflowChecks on}
  
 +
var
 +
n: nativeInt;
  
 +
begin
 +
n := high(n);
 +
n := n + 1;  // will yield RTE 215
 +
end.
 +
</syntaxhighlight>
  
 +
The generated code by the <syntaxhighlight lang="pascal" inline>{$overflowChecks}</syntaxhighlight> directive is the ''most efficient'', since it directly uses available status flag evaluation instructions (e.g. “jump if overflow occured”).
 +
On the downside, a once triggered RTE will inevitably terminate the program.
 +
If this is regarded as counter-productive, you would have to recognize situations leading to overflows on your own:
 +
<syntaxhighlight lang="pascal" line highlight="12-18">
 +
program overflowAnticipation(input, output, stderr);
  
 +
var
 +
n: {$ifdef CPU64} int64 {$else} longint {$endif};
  
The symbol '''''-''''' (pronounced "minus") is used to substract two numbers (the number on left minus the number on right), the result is a number.
+
begin
If the right number is greater than the left number, the result should be a signed number.
+
// untreated
 +
n := high(n);
 +
n := n + 1;
 +
writeLn(n); // prints low(n)
 +
 +
// anticipated: reverse operation and comparison w/ 1st operand
 +
n := high(n);
 +
if high(n) - 1 < n then
 +
begin
 +
halt(1);
 +
end;
 +
n := n + 1;
 +
writeLn(n);
 +
end.
 +
</syntaxhighlight>
  
A := 1 - 3; // -> A = -2
+
Obviously this won't be as efficient as testing the overflow status flag, and here, without any ''re-used'' [[Constant|constant]], is even prone to programming errors (consider the situation changing the subtrahend in one line of code only).
  
 
{{Symbols}}
 
{{Symbols}}
{{Stub}}
 
[[Category:Pascal]]
 
[[Category:Symbols]]
 

Latest revision as of 17:10, 6 August 2022

English (en) suomi (fi) français (fr) русский (ru)

-

In ASCII, the character code decimal 45 (or hexadecimal 2D) is defined to be - (hyphen-minus).

Occurrences

The symbol - (pronounced “minus”) is used to

  • indicate the negative sign of a number literal
  • subtract two numbers (using infix notation)
  • form the difference of two sets.
program minusDemo(input, output, stderr);

var
	x: longint;
	g: longint;
	m: set of (foo, bar);

begin
	// unary operator: negative sign
	x := -42;                     // x becomes negative 42
	
	// binary operator: difference of numbers
	g := 144 - 169;               // g becomes negative 25
	
	// binary operator: difference of sets
	m := [foo, bar] - [bar];      // m becomes {foo}
end.

Minus is also a unary operator. You can write such stupid expressions as ----+--+--+--8.

Operation with numbers

Beware: The result's target of subtractions (and sign inversions) should be a signed integer. If it's not, with {$rangechecks} directive enabled, it will possibly cause a run-time error. In any other case an arithmetically wrong result is produced.

program faultySubtraction(input, output, stderr);

var
	x, y: longword;

begin
	y := 1;
	{$push}
	{$rangechecks off} // otherwise the next expression
	x := 0 - y;        // yields RTE 201
	{$pop}
	
	writeLn(x);
end.

This program prints 4294967295, which equals to high(longword) because of the (unsigned) integer overflow.

However note, there are situations where negative signs do not necessarily provoke an error. Attempting to store a “negative” zero won't harm:

 1program minusOperations(input, output, stderr);
 2
 3{$rangeChecks on}
 4
 5var
 6	n: longword;
 7
 8begin
 9	// "negative" zero equals to (sign-less) zero
10	n := 0;
11	n := -n;

Also note, arithmetic integer operations are done with the processor's native integer type. Although intermediate results fall out of range, the code generated by {$rangechecks on} ensures the type's boundaries aren't exceeded after the result's already stored.

13	// intermediate results can be out of range:
14	n := 1;
15	n := n - n - n + 1;
16end.

This whole program will finish with an exitCode of zero (that means “successful” [actual value might vary among platforms]).

In consequence of the latter mentioned behavior: Integer overflows in the processor's native type can not be caught (in that way). In assembler you would have access evaluating several status flags, but in Pascal you do not. Instead you can use {$overflowChecks} which will evoke a run-time error.

 1program overflowChecksDemo(input, output, stderr);
 2
 3{$overflowChecks on}
 4
 5var
 6	n: nativeInt;
 7
 8begin
 9	n := high(n);
10	n := n + 1;   // will yield RTE 215
11end.

The generated code by the {$overflowChecks} directive is the most efficient, since it directly uses available status flag evaluation instructions (e.g. “jump if overflow occured”). On the downside, a once triggered RTE will inevitably terminate the program. If this is regarded as counter-productive, you would have to recognize situations leading to overflows on your own:

 1program overflowAnticipation(input, output, stderr);
 2
 3var
 4	n: {$ifdef CPU64} int64 {$else} longint {$endif};
 5
 6begin
 7	// untreated
 8	n := high(n);
 9	n := n + 1;
10	writeLn(n); // prints low(n)
11	
12	// anticipated: reverse operation and comparison w/ 1st operand
13	n := high(n);
14	if high(n) - 1 < n then
15	begin
16		halt(1);
17	end;
18	n := n + 1;
19	writeLn(n);
20end.

Obviously this won't be as efficient as testing the overflow status flag, and here, without any re-used constant, is even prone to programming errors (consider the situation changing the subtrahend in one line of code only).


navigation bar: topic: Pascal symbols
single characters

+ (plus)  •  - (minus)  •  * (asterisk)  •  / (slash)
= (equal)  •  > (greater than)  •  < (less than)
. (period)  •  : (colon)  •  ; (semi colon)
^ (hat)  •  @ (at)
$ (dollar sign)  •  & (ampersand)  •  # (hash)
' (single quote)

character pairs

<> (not equal)  •  <= (less than or equal)  •  := (becomes)  •  >= (greater than or equal)

 •  >< (symmetric difference)  •  // (double slash)