Negation of an Arbitrary Number: Challenge!

This is a challenge I have come up with; however, I do not know the answer: I am asking for it. Note that there is no prize besides the intellectual gain.

Here it is:

For any arbitrary number (float, negative, etc.), logically negate it using math.
i.e. If my input to your program/function is 500, I should get 0. Successive calls should return 1, then 0, then 1, etc. As mentioned above, it must also work for negative and floating-point numbers.

Restrictions:
No conditionals. Only math. (add, subtract, divide, multiply, maybe modulus). You may use some functions, such as abs().
No exclamation point (!).
It must be one single equation.
You may not use variables besides the input.
No storing data in non-volatile memory for the next program iteration.

I'm just wondering whether or not this is possible, or if ! is the only way.

I did come up with this so far:

output = 1 + (-1) * input

but it only works if the inputs are 1 or 0... not for floats or negative numbers or high numbers like 129.

Good luck!

baum

P.S. this is not homework if you were wondering. :slight_smile:

unsigned long output = input <<32 +1;

unsigned long output = input <<32 +1;

So if input is 500 (111110100) then 500<<2 = 2000, 2000+1 = 2001

????

What output do you want for an input of 0 or 0.0?

"So if input is 500 (111110100) then 500<<2 = 2000, 2000+1 = 2001"

No, I had <<32, not 2.

unsigned long is 32, so any number shifted left 32 bits would always be 0, and adding 1 would yield 1.
More of a joke answer :slight_smile:
I could have said
output = input *0 + 1; for the same.

What's the point of this exercise baum?
Will the "successive calls" be the output from the first call, or a newly inputted #?

For any arbitrary number (float, negative, etc.), negate it using math.
i.e. If my input to your program/function is 500, I should get 0. Successive calls should return 1, then 0, then 1, etc. As mentioned above, it must also work for negative and floating-point numbers.

What? I thought negation meant make negative, e.g. 500 becomes -500
And I don't see how you can use just math (conditional logic) to get two different answers from the same input.

Crossroads: sorry, i meant to type "32." but 500<<32 would overflow, would it not? It should return 0, much like the '!' operator. (the function should work for ALL successive calls)

What's the point of this exercise baum?

It's a programming exercise. And "successive calls" could be any number. It could be the output from the last call, or a new number. Either one.

dc42: Here is a truth table:

INPUT OUTPUT
0,0.0 1 <-- zero returns 1
anything else 0 <-- all else returns 0, includes negatives, floats, etc.

WizendEE:

sorry... should have said logical negation. I will edit the original. Think of the function to operate like '!'

baum

Your rules conflict:

"You may not use variables besides the input.
No storing data in non-volatile memory for the next program iteration."
vs
"And "successive calls" could be any number. It could be the output from the last call,"
How would one do that without storing the prior output somewhere?

You may not store anything from within the function. You could write a program that called your function many times, but the function itself can not use any variables, etc. from within.

baum

[INPUT OUTPUT
0,0.0 1 <-- zero returns 1
anything else 0 <-- all else returns 0, includes negatives, floats, etc./quote]

It look to me a NAND gate with 3 inputs...

So the question can be condensed down to:

Find a way to implement the logical NOT command (!) with only addition, subtraction, multiplication, division, and absolute value. It must work with signed and unsigned integers and floats.

The negative part is pretty easy; just absolute value it.

output = input <<32 +1;

Hey all of you, please first make me understand that what does << sign used for????
:~

@Saad Khalil

<< <-- that mean ---> bit shift left

example: 0110 << 1 = 1100

Check the IDE , in help.. reference.. for more details.

for ints, longs and the IEE754 float the value 0 are bitwise all 0's.

Solution to the problem is to OR up all individual bits and subtract the "or-sum" from 1 : only bitmath and one subtraction;

something like this?

void setup()
{
  Serial.begin(115200);
  int y = func(0.0);
  Serial.println(y);
  y = func(1.0);
  Serial.println(y);
  y = func(-10.0);
  Serial.println(y);
}

// only a type declaration outside the function, no memory :)
union U 
{
  unsigned long x;
  float f;
};

int func(float f)
{
  U u;
  u.f = f;

  int rv = 0;
  for (int i=0; i<32; i++) 
  {
    rv |= bitRead(u.x, i);
  }
  return 1-rv;
}

void loop(){}

Note the loop can be unrolled to one expression see below

int func(float f)
{
  U u;
  u.f = f;
  return 1 - ( bitRead(u.x, 0) | bitRead(u.x, 1) ...  bitRead(u.x, 30) | bitRead(u.x, 31)) ;  
}

Thanks Techone..got it.. i just forgot that..

Nice @robtillaart!

Looks pretty good. But what if I have an arbitrary data type, too? A byte, for example, wouldn't work with your function. So without using something like a template, can it be done with a single, one-line function that works for all real numbers? (It's really more of a math problem than a CS/programming question...)

baum

p.s. I think I have an idea... It involves the sign() function, which is not commonly used in mathematics (but it is allowed here, as are other math functions... sin, cos, tan, etc.) Also, the sign() function can be (sort of) represented by abs(x)/x (but it doesn't work for zero). That is your hint. Maybe a graph of the sign function will help.

For a big hint:
Graph from wolfram|alpha Try substituting 0 in for x... see what happens.

baum