Difference between revisions of "Minus"

From Lazarus wiki
Jump to navigationJump to search
(→‎occurrences: unary operator)
 
(4 intermediate revisions by 3 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>  
+
In [[ASCII]], the character code decimal <syntaxhighlight lang="pascal" inline>45</syntaxhighlight>  
(or [[Hexadecimal|hexadecimal]] <syntaxhighlight lang="pascal" enclose="none">2D</syntaxhighlight>) is defined to be  
+
(or [[Hexadecimal|hexadecimal]] <syntaxhighlight lang="pascal" inline>2D</syntaxhighlight>) is defined to be  
<syntaxhighlight lang="pascal" enclose="none">-</syntaxhighlight> (hyphen-minus).
+
<syntaxhighlight lang="pascal" inline>-</syntaxhighlight> (hyphen-minus).
  
== occurrences ==
+
== Occurrences ==
  
The symbol <syntaxhighlight lang="pascal" enclose="none">-</syntaxhighlight> (pronounced “minus”) is used to
+
The symbol <syntaxhighlight lang="pascal" inline>-</syntaxhighlight> (pronounced “minus”) is used to
 
* indicate the negative sign of a number literal
 
* indicate the negative sign of a number literal
 
* subtract two numbers (using infix notation)
 
* subtract two numbers (using infix notation)
Line 34: Line 34:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Minus is also unary operator.
+
Minus is also a unary operator.
You can write such stupid expressions as <syntaxhighlight lang="pascal" enclose="none">----+--+--+--8</syntaxhighlight>.
+
You can write such stupid expressions as <syntaxhighlight lang="pascal" inline>----+--+--+--8</syntaxhighlight>.
  
== operation with numbers ==
+
== Operation with numbers ==
  
 
Beware:
 
Beware:
 
The result's target of subtractions (and sign inversions) 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 possibly cause a run-time error.
+
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.
 
In any other case an arithmetically wrong result is produced.
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 59: 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" 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.
 
However note, there are situations where negative signs do not necessarily provoke an error.
 
Attempting to store a “negative” zero won't harm:
 
Attempting to store a “negative” zero won't harm:
 +
 
<syntaxhighlight lang="pascal" line>
 
<syntaxhighlight lang="pascal" line>
 
program minusOperations(input, output, stderr);
 
program minusOperations(input, output, stderr);
Line 78: Line 80:
  
 
Also note, arithmetic integer operations are done with the processor's native integer type.
 
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.
+
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">
 
<syntaxhighlight lang="pascal" line start="13">
 
// intermediate results can be out of range:
 
// intermediate results can be out of range:
Line 86: Line 88:
 
</syntaxhighlight>
 
</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]).
+
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:
 
In consequence of the latter mentioned behavior:
 
Integer overflows in the processor's native type can not be caught (in that way).
 
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.
+
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.
+
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">
 
<syntaxhighlight lang="pascal" line highlight="3,10">
Line 99: Line 101:
  
 
var
 
var
n: {$ifdef CPU64} int64 {$else} longint {$endif};
+
n: nativeInt;
  
 
begin
 
begin
Line 107: Line 109:
 
</syntaxhighlight>
 
</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”).
+
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.
 
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:
 
If this is regarded as counter-productive, you would have to recognize situations leading to overflows on your own:
Line 136: Line 138:
  
 
{{Symbols}}
 
{{Symbols}}
 
[[Category:Code]]
 

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)