I was creating a scoring formula for a game.

The formula in question is

millis() * 1.1 ^ (millis()/10000);

However, I'm having trouble understanding the different error messages that the Arduino IDE is projecting to me

invalid operands of type to binary operator

I have declared the score as an unsigned long.

  • ^ is the binary exclusive-or operation. You are probably trying to raise it to the power of. Use pow(base, exponent) instead. – Kwasmich Sep 28 '18 at 10:54
  • Creating two declarations, score = millis() * 1.1 and divisor = millis()/10000 and then creating a new unsigned long machinescore = pow(score, divisor) outputs consistent 1's. does it have anything to do with it being integer math? as such it wont display anything until something is greater than another? – Reid Pilkington Sep 28 '18 at 11:03
  • add a .0 for the divisor: 'millis()/10000.0'. Hopefully you've also declared both score and divisor as floating point numbers. Also the result will be a floating point number. This is basic C programming language stuff. You can try it on your local machine instead of uploading it to the board every time you try to figure out something. – Kwasmich Sep 28 '18 at 11:09
  • Thank you so much, ive been working on other projects hence the arduino IDE. cant wrap my head around basic principals at the moment. – Reid Pilkington Sep 28 '18 at 11:15

I would avoid calling millis() twice within the same expression. Not really a big deal in your case, but the two calls can very well return different values, which would make your formula slightly inconsistent. Then, using the proper syntax for the power function, as explained by Kwasmich:

uint32_t t = millis();
float score = t * pow(1.1, t/1e4);

Note that 1e4 is the scientific notation for 10000.0. I personally find the former more readable, as you don't have to count the zeros.

Now, it is worth noting that the pow() function is very expensive to compute on this kind of 8-bit FPU-less processor. It involves both a logarithm and an exponential. The second line is essentially equivalent to

float score = t * exp(t/1e4 * log(1.1));

The floating point division is also quite expensive. You could save something like half the processing cycles by pre-computing log(1.1)/1e4 and using the result in your expression:

float score = t * exp(t * 9.53e-6);
  • Thanks for that, i added it in and it works as the graph shows. I do have another question if you could help. I'm preparing the score to send via UART so i need to convert the score in 4 8bit packets, my way of thinking is using modulus 256 and storing the frames in a respective variable to send, but i can only think of how to do it once, leaving me with 24 more bits to shift and send. cheers for any help. – Reid Pilkington Sep 29 '18 at 4:09
  • 1
    @ReidPilkington: To send numeric data through the serial port, use Serial.println(score). This will format the number in ASCII. If that can't work for you, open another question, explain why ASCII won't do it, and provide a complete specification of the binary format you want (IEEE 754 v.s. integer, endianness...). – Edgar Bonet Sep 29 '18 at 9:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.