0
const unsigned long C1 = 30 * 1000;
const unsigned long C2 = (300 * 1000)/C1; // must be = 10

void setup() {
  Serial.begin(57600);
  Serial.println("\n-------");
  Serial.print("C1 = "); Serial.println(C1);
  Serial.print("C2 = "); Serial.println(C2);

  unsigned long V1 = (300 * 1000)/C1;   // must be = 10
  Serial.print("V1 = "); Serial.println(V1);

  long V2 = (300 * 1000)/30000; // must be = 10
  Serial.print("V2 = "); Serial.println(V2);

  int V3 = (300 * 1000)/30000; // must be = 10
  Serial.print("V3 = "); Serial.println(V3);
}

void loop() {
}

Arduino UNO printed in monitor console:

C1 = 30000   (ok)
C2 = 143164  (must be = 10)
V1 = 143164  (must be = 10)
V2 = 0       (must be = 10)
V3 = 0       (must be = 10)

What is wrong?

  • 1
    Hack long V2 = (300 * 1000UL)/30000; printed 10 – tim4dev Feb 6 '16 at 19:33
5
300

and

1000

are integers.

What

long V2 = (300 * 1000)/30000;

really does is take the integers 300 and 1000 multiply them. This calculation overflows, and equals -27680. Dividing that by 30000 yields 0. What you added in your comment isn't a hack, it's the proper solution. By including the suffix L or UL you tell the compiler that you want longs, not ints.

2

What is wrong?

You are assuming that the expression is long int but it is actually int. The literals are int. You need to convince the compiler that the expression is actually long int. That can be done by cast:

((long) 30000)

or literal long integer syntax:

30000L

The AVR GCC compiler uses int defined as 16-bit. Expression and literals are implict 16-bit.

More on the representation of C/C++ data types, expressions, and calling conventions can be found here.

Cheers!

2

A good practice with literal numbers which you want to divide and multiply is to always define them as double, and convert them to integer when they are used. This is often the case with frequency/period constants. This prevents most catastrophic overflow / rounding errors that integer math would have, while allowing you to use consistent units in your definitions.

 #define F_CPU 16000000.0   // in Hz
 #define F_TICK (1.0/F_CPU) // in seconds
 #define DELAY 0.001        // in seconds
 #define COUNT ((uint16)(DELAY/F_TICK))
 Serial.println(COUNT);

Of course, you can calculate the number of CPU ticks per millisecond using fixed-point math, for example by defining the frequency in MHz and the tick time in nanoseconds, but you'll have to scratch your head every time you need to convert a period to a frequency and vice versa, and you'll have to change units the moment your frequency will not be a multiple of MHz.

-2

This is my code for your problem:

unsigned long mul(long num1, long num2)
{
  unsigned long res, add = 0;
  while (num1 > 65000)
  {
    num1 -= 65000;
    add++;
  }
  res = unsigned(num1 * num2);
  while(add)
  {
    res +=65000;
    add--;
  }
  return (res + add);
}
  • 1
    This does not solve any problem, is not useful for anything, and can potentially cost huge amounts of CPU time. – Edgar Bonet Oct 5 '18 at 12:18

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.