Just a quick question
printf("%d", 99 || 44) prints "1" in C
print 99 || 44 prints "99" in perl
There are two different kinds of evaluation. Does each one have a name?
edit: i'm interested to know how this Perl evaluation is commonly called when compared to C. When you say "C example is X, and perl example is not X, but Y" which words would you use for X and Y. "short circuit" is not what i'm looking for.
Read here.
Binary || performs a short-circuit logical OR operation. That is, if the left operand is true, the right operand is not even evaluated. Scalar or list context propagates down to the right operand if it is evaluated.
In Perl the || and && operators differ from C's in that, rather than returning 0 or 1, they return the last value evaluated.
printf("%d", 99 || 44) prints "1" in C
That is because 99||44 returns true(only 99(which is non-zero) is evaluated due to the short-circuiting action of || ) whose equivalent is 1 hence printf() prints 1.
print 99 || 44 prints "99" in perl
..rather than returning 0 or 1, the last value evaluated(99 here) is returned.
As you note, the words you are looking for are not "short-circuit". Short-circuit evaluation means that in the expression
e1 || e2
if expression e1 is evaluated to something representing truth, then it is not necessary to evaluate e2. Both C and Perl use short-circuit evaluation.
I'm aware of the distinction you make in two different flavors of short-circuit OR, but in twenty years of working in programming languages I have never seen these things named. The Perl version is quite popular in dynamic languages, e.g., Icon, Lua, Scheme.
The Perl version is almost expressible in C:
e1 ? e1 : e2
Unfortunately this version may evaluate e1 twice, depending on the optimizer—and if e1 has side effects, or if the compiler can't tell if it might have side effects, then the compiler is required to evaluated it twice. This defect can be fixed by binding the value of e1 to a fresh local variable, but that requires a GNU extension.
The C behavior can be emulated in Perl by
!!(e1 || e2)
The C version uses || as the logical OR between the two values. Both 44 and 99 evaluate to true in C as they are not 0, so the result of an OR between them returns 1 (AKA true in C)
In that particular perl snippet, || is the null-coalescing operator, an binary which evaluates to the second argument if the first is null, otherwise evaluating to the first argument. Since 99 is the first argument and not null, it gets returned and printed.
EDIT: Thanks Evan for the clafication: The || operator in perl is not the null-coalescing operator, it returns the RHS if the LHS evaluates to false, other wise returning the LHS. // is the "proper" null-coalescing operator.
Here's the list of values in perl that evaluate to false (from wikipedia)
$false = 0; # the number zero
$false = 0.0; # the number zero as a float
$false = 0b0; # the number zero in binary
$false = 0x0; # the number zero in hexadecimal
$false = '0'; # the string zero
$false = ""; # the empty string
$false = undef; # the return value from undef
$false = 2-3+1 # computes to 0 which is converted to "0" so it is false
In Perl, 99 || 44 returns 99, because || is "short circuiting" and if its first argument is true in boolean context, it just returns it. print prints 99.
In C the result of || is logical, which passed to printf results either in 1 or 0. It's also short-circuiting, so 44 isn't even evaluated.
Both C and Perl refer to their respective || operators as a "logical OR" (as distinct from a bit-wise OR). There's no special name for Perl's behavior of returning the last value as opposed to 0 or 1.
In C, || is a Boolean operation. In Perl it is an integer type-agnostic operation which happens to treat the first argument as a Boolean value. That is the only distinction.
Related
I have a problem relative to some C++ code about the !! operator. It gives me an unexpected result and I don't understand why:
int x=-12;
x=!!x;
print("value=",x);
The output of this is 1. But i do not know how. Can anyone explain this ambiguous result?
!!x is grouped as !(!x).
!x is 0 if x is non-zero, and 1 if x is zero.
Applying ! to that reverses the result.
So, !!x can be viewed as a way of setting x to 1 if it's not zero, and remaining at 0 if it's zero. In other words x = !!x is the same as x = x ? 1 : 0.
... !(-12) kindly explain this expression.
It's "logical not of -12". In C++ numeric value 0 is false in logical way, and any non-zero value is true in logical way. This is how C and C++ evaluates numerical values in boolean context, like if (expression) ..., i.e. if (-12) exit(1); will exit your application, because -12 is "true".
When you typecast numeric value to bool type and then back to int, the true will become value 1, but most of the time you can avoid these conversions and use intermediate results of numerical calculations directly, where any non-zero value is "true".
So "not of true" is value false. I.e. !(-12) == false. And !false == true. And you convert the logical value "true" back to int, which will make x == 1.
The !!(numeric_value) is idiomatic way in C++ (and in C too) to "normalize" any numeric value into precisely 0 or 1 (and you may encounter it in source code of many applications).
The "logical" distinction is important, because C++ has also binary operators, where the calculation is working per individual bits, not with value as whole. In "binary" way the "!" operator sibling is ~. Similar example to yours with bit-complement operator x=~~x; would then result into original value -12, because every bit of x is flipped twice, ending with same value as it did start. So ~~x is not something to encounter in regular source, as it's basically "no operation" (contrary to !! which is "no operation" only if the original value was already 0 or 1).
Also this is sometimes source of bugs for people learning the language, as they forget about the distinction and write something like
if (4 & 2) { /* this is "and" so it should be true??? */ }
// it will be false, because in binary way 4&2 == 0
if (4 && 2) { /* this is logical "and" and will be "true" */ }
// because 4 is non-zero, 2 is non-zero, and "true and true" is "true"
I.e. binary operators are & | ~ ^ (and, or, not, xor), and their logical siblings are && || ! for "and, or, not", the logical "xor" doesn't have operator in C++.
I am new to C++, I am trying to understand a piece of code written in C++, here px is an integer, Could please tell me, if the following line is
doing something like if statement. Is it saying if pos.x is equal to residues[n-1] put it in px or vice versa?
px = (res->pos.x == residues[n-1]->pos.x) & (res->pos.x == residues[n+1]->pos.x);
Thanks a lot for your help
The & in this expression is a bitwise AND operation.
It takes the result of the comparison in both of the parentheses and does a bitwise AND on them.
In the left parentheses, it compares the x value of res to the x value of residues[n-1]. A true result is pretty much 1 and false is 0, so it pretty much evaluates to either 1 or 0.
In the right parentheses, you have the same comparison but at index n+1 now. Same things apply.
If both parentheses are true, the bitwise AND evaluates to 1 (true), else 0 (false).
px is probably an integer that is either 1 or 0 and it will hold 1 if both of the comparisons were true in the expression, otherwise it will hold 0. (It acts as a Boolean)
This question already has answers here:
Why can't we use bitwise operators on float & double data types
(2 answers)
Closed 7 years ago.
These are two simple samples in C++ written on Dev-cpp C++ 5.4.2:
float a, b, c;
if (a | b & a | c)
printf("x = %.2f\tF = %.0f\n", x, F);
else
printf("x = %.2f\tF = %.2f\n", x, F);
and this code :
float a, b, c;
if (a || b && a || c)
printf("x = %.2f\tF = %.0f\n", x, F);
else
printf("x = %.2f\tF = %.2f\n", x, F);
Can somebody tell my difference between || > | and & > &&. The second code works , but first does not.
And compiler gives an error message :
[Error] invalid operands of types 'float' and 'float' to binary 'operator&'.
The operators |, &, and ~ act on individual bits in parallel. They can be used only on integer types. a | b does an independent OR operation of each bit of a with the corresponding bit of b to generate that bit of the result.
The operators ||, &&, and ! act on each entire operand as a single true/false value. Any data type can be used that implicitly converts to bool. Many data types, including float implicitly convert to bool with an implied !=0 operation.
|| and && also "short circuit". That means whenever the value of the result can be determined by just the first operand, the second is not evaluated. Example:
ptr && (*ptr==7) If ptr is zero, the result is false without any risk of seg faulting by dereferencing zero.
You could contrast that with (int)ptr & (*ptr). Ignoring the fact that this would be a bizarre operation to even want, if (int)ptr were zero, the entire result would be zero, so a human might think you don't need the second operand in that case. But the program will likely compute both anyway.
You seems be confused with the symbols of the operators. Theses symbols are actually split in two different categories, which are bit-wise operators and logical operators. Although they use the same symbols, you should regard them as different operators. The truth tables for both categories are similar, but the meanings are different. Maybe that's why people use the similar symbols for the operators.
bit-wise operators
~ // NOT
& // AND
| // OR
^ // XOR
The bit-wise operators will regard all its operands as binary numerals and act according to the bit-wise truth tables on every bit of the operands.
Bit-wise Truth Table
x y x&y x|y x^y
0 0 0 0 0
1 0 0 1 1
0 1 0 1 1
1 1 1 1 0
x ~x
0 1
1 0
logical operators
! // Logical NOT (negation)
&& // Logical AND (conjunction)
|| // Logical OR (disjunction)
The logical operator will regard all its operands as bools and act according the operator truth tables. Any number that is not equal to 0 will be true, else will be false.
Logical Truth Table
x y x&&y x||y
F F F F
T F F T
F T F T
T T T T
x !x
F T
T F
For example:
int a = 10; // a = 0000 .... 0000 1010 <-- a 32 bits integer
// a is not zero -> true
int b = 7; // b = 0000 .... 0000 0111 <-- a 32 bits integer
// b is not zero -> true
Then for bit-wise operator:
assert(a & b == 2); // 2 = 0000 .... 0000 0010 <-- every bit will & separately
For logic operator:
assert(a && b == true); // true && true -> true
The bitwise operators, which are | (OR), & (AND), ^ (XOR), and ~ (complement) do what you expect them to do: they perform the aforementioned operations on bits.
And regarding your compilation issue, there are no bitwise operations for floating point numbers.
The logical operators, which are || (OR), && (AND), and ! (NOT) only know the values true and false.
An expression is true if its value is not 0. It is false if its value equals 0.
The logical operators do this operation first. Then they perform their corresponding operation:
||: true if at least one the operands is true
&&: true if both operands are true
!: true if the operand is false
Note that all logical operators are short-circuit operators.
Bitwise operation is not supported for floating points
Alternatively if you really need to check, you can cast before you use them (highly discouraged),
Check here how to convert a float into integrals, https://www.cs.tut.fi/~jkorpela/round.html
This question already has answers here:
What is the "-->" operator in C++?
(29 answers)
Closed 8 years ago.
In the question What is the "-->" operator in C++? it asks what --> does and gives a link to a comp.lang.c++.moderated thread. scrolling down the thread a bit further found me this:
> There is no such operator in C++.
> It's just a combination of two operators: postfix decrement "--" and
> greater ">".
> That's why this example works.
> Try ( x --> 20 ) and you'll get no output in this case;)
Of course there is. It is described together with "runs to" operator:
#include <stdio.h>
int main()
{
int x = 10;
while( x -->> 0 ) // x runs to 0
printf("%d ", x);
}
What does the "runs to" operator actually do?
while( x -->> 0 ) // x runs to 0
This is actually a hybrid of the -- (post-decrement) and >> (bitshift right) operators, better formatted as:
while (x-- >> 0) ...
For this specific usage, with 0 on the right hand side, x is decremented with each loop iteration due to the postfix --, and the prior (pre-decrement) value is shifted right 0 bits by >> 0 which does nothing at all when x is non-negative, so the statement could be simplified to:
while (x--) ...
When x is 1 that's non-zero so found true for the purposes of the while test, then post-decrement reduces it to 0 and the loop executes for the last time (with x being 0 during that iteration); the next time while (x--) is checked with x already 0, the while loop terminates, with x left wrapping to the highest representable value for the unsigned type.
More generally, if you try to use >> on a negative value (e.g. x starts at 0 or a negative value great than INT_MIN, so x-- yields a negative value) the result is implementation defined, which means you have to consult your compiler documentation. You could use your compiler documentation to reason about how it would behave in the loop....
Relevant part of the Standard: 5.8/3:
The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a non-negative value, the value of the result is the integral part of the quotient of E1/2^E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
BTW /- for Visual Studio, per http://msdn.microsoft.com/en-us/library/336xbhcz.aspx, the implementation defined behaviour is "No shift operation is performed if additive-expression is 0.". I can't find anything in the GCC manual about this (would have expected it here).
while( x -->> 0 ) // x runs to 0
No, the "goes to operator" is --> with only one > sign. It decreases x by one and then compares the result to zero.
The -- >> 0 "runs to operator" decreases x and then bitshifts the result rightward by zero. Bitshifting by zero does nothing for nonnegative x, otherwise it's implementation-defined (usually does nothing, but could be random). Zero bitshifted by zero is zero, which is interpreted as false, at which point the loop will terminate.
So it "works" but it's a terrible way of expressing a loop.
-- decrements but returns the value of the variable before it was decremented, >> shifts to the right by the right operand, which is 0 (a.k.a. a no-op), then it implicitly compares the result against 0.
I've been struggling for a while with a part of my code and I finally found that the problem lies with a simple test that don't give me the result I expect.
if (2) //=> true
if (2 & true) //=> false
if (bool(2) & true) //=> true
What I don't understand is why the second line results in false.
My understanding was that every non-zero integer was considered as true in a test.
Because the bitwise and between 2 and true is false.
& (bitwise operator) is different than && (logical operator).
true cast to int is 1.
So 2 & true is 2 & 1 which is false - because 0000000000000010 & 0000000000000001 == 0. (bits may vary)
Whereas bool(2) == 1, and 1 & 1 is true.
if (2) //=> true
So far, so good.
if (2 & true) //=> false
The condition here evaluates to 2 & 1 == 0, because & is a bitwise operator and 2 and 1 are respectively 00000010 and 00000001 in binary.
if (bool(2) & true) //=> true
Interestingly enough, on my compiler I seem to recall erratic behavior in some cases like this; and, if sect. 4.12 of the C++11 standard addresses the matter, it does so in a manner I do not understand. I seem to recall seeing my compiler let bool(2) == 2, which one would not expect. Whether this represents a bug in my compiler or a fault in my recollection, I do not know.
I suspect however that you want the logical operator && rather than the bitwise operator &.
QUIZ
To check your understanding, try
if (3 & true) //=> true
Do you understand why? (Hint: the binary representation of 3 is 00000011.)
You need && instead of &.
&& is the boolean and operator, whereas & is the binary 'and' so 2 & true is the same as 0010 & 0001 = 0000 -> false whereas 2 && true = true.
& does an AND between all the bits (call bitwise AND) , what you need is the && operator (boolean AND).
2 in binary is '10' and true is 1 (01) in binary, the result 10 & 01 is therefore 0 .
bool(2) convert 2 to true , is 01 in binary, and 01 & 01 is 01.