Difference between revisions of "Minus"

From Lazarus wiki
Jump to navigationJump to search
(add content, remove Template:Stub)
m (Removed category included in page template)
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{Minus}}
 
{{Minus}}
  
<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>
+
<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" enclose="none">45</syntaxhighlight>
 +
(or [[Hexadecimal|hexadecimal]] <syntaxhighlight lang="pascal" enclose="none">2D</syntaxhighlight>) is defined to be
 +
<syntaxhighlight lang="pascal" enclose="none">-</syntaxhighlight> (hyphen-minus).
 +
 
 +
== Occurrences ==
  
 
The symbol <syntaxhighlight lang="pascal" enclose="none">-</syntaxhighlight> (pronounced “minus”) is used to
 
The symbol <syntaxhighlight lang="pascal" enclose="none">-</syntaxhighlight> (pronounced “minus”) is used to
* indicate the negative sign of a number
+
* indicate the negative sign of a number literal
 
* subtract two numbers (using infix notation)
 
* subtract two numbers (using infix notation)
* form the difference of two sets.
+
* form the difference of two [[Set|sets]].
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 27: Line 33:
 
end.
 
end.
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
Minus is also a unary operator.
 +
You can write such stupid expressions as <syntaxhighlight lang="pascal" enclose="none">----+--+--+--8</syntaxhighlight>.
 +
 +
== Operation with numbers ==
  
 
Beware:
 
Beware:
The result's target of subtractions should be a ''signed'' integer.
+
The result's target of subtractions (and sign inversions) should be a ''signed'' integer.
If it's not, with [[sRangechecks|<syntaxhighlight lang="pascal" enclose="none">{$rangechecks}}</syntaxhighlight>]] enabled, it will cause an Run-time error.
+
If it's not, with [[sRangechecks|<syntaxhighlight lang="pascal" enclose="none">{$rangechecks}</syntaxhighlight>]] [[Compiler directive|directive]] enabled, it will possibly cause a [[runtime error|run-time error]].
Otherwise an arithmetically wrong result is produced.
+
In any other case an arithmetically wrong result is produced.
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
program faultySubtraction(input, output, stderr);
 
program faultySubtraction(input, output, stderr);
Line 48: Line 59:
 
end.
 
end.
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 
This program prints <syntaxhighlight lang="pascal" enclose="none">4294967295</syntaxhighlight>, which equals to <syntaxhighlight lang="pascal" enclose="none">high(longword)</syntaxhighlight> because of the (unsigned) integer overflow.
 
This program prints <syntaxhighlight lang="pascal" enclose="none">4294967295</syntaxhighlight>, which equals to <syntaxhighlight lang="pascal" enclose="none">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);
 +
 +
{$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" enclose="none">{$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>
 +
 +
This whole program will finish with an {{Doc|package=RTL|unit=system|identifier=exitcode|text=<syntaxhighlight lang="pascal" enclose="none">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" enclose="none">{$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" enclose="none">{$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};
 +
 +
begin
 +
// 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>
 +
 +
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}}
 
[[Category:Pascal]]
 
[[Category:Symbols]]
 

Revision as of 00:59, 21 February 2020

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)