What the following expression computes, exactly?
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
what yields if x is zero, less than zero, more than zero?
I guess I know the answer, but I'd like to check for clarity...
Thank you
EDIT: added missing parenthesis
EDIT: more info here
First, the macro doesn't compute anything. It is substituted into a source code, expanded, and the resulting text gets compiled. What the resulting text is, depends on the way you use the macro, especially on what parameter you give.
Second, the macro lacks one closing paren, so it probably would not give you a meaningful expression to be compiled.
Third, even when you add the lacking paren:
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
it is possible you get unexpected results if you use the macro in a non-simplest way. For example,
SIGN(a ^ b)
would result in
((a ^ b < 0) ? -1 : (a ^ b > 0))
which is interpreted in C and C++ as
((a ^ (b < 0)) ? -1 : (a ^ (b > 0)))
which certainly is not what we intend.
You should add parentheses to avoid unwanted operators binding – for:
#define SIGN(x) (((x) < 0) ? -1 : ((x) > 0))
the above example will yield a sensible expression
(((a ^ b) < 0) ? -1 : ((a ^ b) > 0))
but that still doesn't protect you against unwanted double increment/decrement in case of plus-plus or minus-minus operators or double execution of a function in case the expression substituted for x contains a function call.
It does exactly what you probably think it does, gives -1 for negative numbers, 0 for zero, and 1 for positive numbers.
However, you should generally avoid function-like macros since they will not do what you expect if, for example, you try to calculate SIGN(value++). Since they're simple text substitutions, that would resolve to:
((value++ < 0) ? -1 : (value++ > 0)
You're far better off just using real functions and letting the compiler inline them if it decides it's worth it. You can also suggest to the compiler that inlining it, with the inline keyword, but keep in mind it is a suggestion.
That macro got a stray parenthesis.
It looks like it is meant to be an implementation of signum function, which returns -1, 1 or 0 depending on value of argument.
For sake of being safe and writing C++ code, it is prudent
to replace macro by template, similar to
template <class T>
int SIGN( T x )
{
return (x < T(0)) ? -1 : (x > T(0));
}
First comparision is argument of trenary operator ?:. Ternary would return -1 if expression evaluates to true , i.e. x is less than 0, otherwise it would return result of x > T(0).
That expression would evaluated to 0 if x equals to 0, otherwise it would be evaluated to 1.
Note that my implementation is not ideal, you can find better implementation elsewhere on SO.
An alternative expression can be:
return (T(0)<x) - (T(0)>x);
Which may be more effective with platforms that implement certain CPU instructions
If you use it with values only and not expressions that macro will produce -1, 0, 1, otherwise you may have serious problems. The tricky part is (x>0). Lets read the standard:
5.9 Relational operators [expr.rel]
The operators < (less than), > (greater than), <= (less than or equal
to), and >= (greater than or equal to) all yield false or true. The
type of the result is bool.
and
3.9.1 Fundamental types [basic.fundamental]
Values of type bool are either true or false. Values of type bool participate in integral promotions (4.5).
Thus x>0 is either true or false.
4.5 Integral promotions [conv.prom]
A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.
and is promoted to either 1 or 0 (respectively).
I am building some test cases for integer/1 using SWI-Prolog.
ISO/IEC 13211-1 gives a BNF definition for integer and one of the alternatives for integer is for a character code constant.
I am able to create and test examples of all the other alternatives using integer/1 but for character code constant I cannot create a valid example. (see below)
How is an integer as a character code constant created that will return true using integer/1?
Answer
Thanks to #false.
integer(0'0).
true.
integer(0'9).
true.
integer(0'a).
true.
integer(0'\n).
true.
Usefulness
X is 0'\n.
X = 10.
X is 0b010101.
X = 21.
X is 0xFFF1.
X = 65521.
X is 0o7423.
X = 3859.
and thanks to j4n bur53 via link from #false
with SWI-Prolog other radix can be used besides 2,8, or 16.
X is 5'1234012340.
X = 3032220.
X is 32'123456789ABCDEFGHIJKLMNOPQRSTU.
X = 47525417447024678661670292427038339608998846.
What I tried
integer("0").
false.
integer('0').
false.
integer(`0`).
false.
integer("1").
false.
integer('1').
false.
integer(`1`).
false.
ISO
INTERNATIONAL STANDARD ISO/IEC 13211-1 First edition 1995-06-01
Information technology - Programming languages - Prolog
Part 1: General Core
INTERNATIONAL STANDARD ISO/IEC 13211-1:1995
TECHNICAL CORRIGENDUM 1
Published 2007-11-15
INTERNATIONAL STANDARD ISO/IEC 13211-1:1995
TECHNICAL CORRIGENDUM 2
Published 2012-02-15
BNF for integer
integer token (* 6.4.4 *) =
integer constant (* 6.4.4 *)
| character code constant (* 6.4.4 *)
| binary constant (* 6.4.4 *)
| octal constant (* 6.4.4 *)
| hexadecimal constant (* 6.4.4 *) ;
BNF for character code constant
character code constant (* 6.4.4 *) =
"0" , single quote char (* 6.5.5 *), single quoted character (* 6.4.2.1 *)
I suspect the BNF is wrong in ISO/IEC 13211-1 but checking the CORRIGENDUM shows no corrections.
Integer test cases
% <integer constant> examples
number(1).
% true.
number(0).
% true.
number(01).
% true.
number(12345678901234567890123456789012345678901234567890).
% true.
% <character code constant> examples
% ???
% <binary constant> examples
number(0b0).
% true.
number(0b10101010101010101010101010101010101010101010101010).
% true.
integer(0b2).
% ERROR: Syntax error: Illegal number
% ERROR: integer
% ERROR: ** here **
% ERROR: (0b2) .
% <octal constant> examples
integer(0o7).
% true.
integer(0o1234567012345670123456701234567012345670123456701234567).
% true.
integer(0o8).
% ERROR: Syntax error: Illegal number
% ERROR: integer
% ERROR: ** here **
% ERROR: (0o8) .
% <hexadecimal constant>
integer(0x0).
% true.
integer(0xF).
% true.
integer(0xf).
% true.
integer(0x123456789ABCDEF012345670123456789ABCDEF012345670123456789ABCDEF).
% true.
integer(0xG).
% ERROR: Syntax error: Illegal number
% ERROR: integer
% ERROR: ** here **
% ERROR: (0xG) .
This was answered by false in a comment.
Reposting here so that others can see an answer exist.
integer(0'0).
true.
integer(0'9).
true.
integer(0'a).
true.
integer(0'\n).
true.
Most programming languages use ~ to represent a unary bitwise-not operation. Go, by contrast, uses ^:
fmt.Println(^1) // Prints -2
Why did the Go designers decide to break with convention here?
Because ^x is equivalent to m ^ x with m = "all bits set to 1" for unsigned x and m = -1 for signed x. Says so in the spec.
It's similar to how -x is 0 - x
I'm learning. This is something I found strange:
let test_treeways x = match x with
| _ when x < 0 -> -1
| _ when x > 0 -> 1
| _ -> 0;;
If I then call it like this:
test_threeways -10;;
I will get type mismatch error (because, as far as I understand, it interprets unary minus as if it was partial function application, so it considers the type of the expression to be int -> int. However, this:
test_threeways (-10);;
acts as expected (though this actually calculates the value, as I could understand, it doesn't pass a constant "minus ten" to the function.
So, how do you write constant negative numbers in OCaml?
You need to enclose it in order to avoid parsing amiguity. "test_threeways -10" could also mean: substract 10 from test_threeways.
And there is no function application involved. Just redefine the unary minus, to see the difference:
#let (~-) = (+) 2 ;; (* See documentation of pervarsives *)
val ( ~- ) : int -> int = <fun>
# let t = -2 ;;
val t : int = -2 (* no function application, constant negative number *)
# -t ;;
- : int = 0 (* function application *)
You can use ~- and ~-. directly (as hinted in the other answer), they are both explicitly prefix operators so parsing them is not ambiguous.
However I prefer using parentheses.
Why does this fail L is [1,2,3,4], and this works: L = [1,2,3]?
But L is 1, and L = 1 both work the same.
is should only be used when evaluating arithmetic operations on the right-hand side.
i.e.:
X is 1 + 2 + 3
is/2 evaluates the right-hand structure as an arithmetic expression. If it is not a valid arithmetic expression or a number, is/2 fails. Otherwise, the number to which the arithmetic expression evaluted is unified with the [presumably] unbound left-hand value.