Program to Multiply Numbers Won't Actually Multiply Them

I am trying to write a program which takes in a number of integers pairs to be multiplied, then prints out the result of each multiplication. Instead of doing this, the program just prints out the number of multiplications and the numbers, but it never does the multiplications or add the newline characters (despite me explicitly using println). In the example below I specify 2 number pairs to multiply, and then enter 3,4,7,8 (entering a NL character after each number, but spaces and commas cause the same problem).

I tried doing this with floats and in that case it will only read in one number, then it prints out a negative result.

void setup() 
{
  Serial.begin(9600);
  Serial.println("Enter the number of Multiplications (up to 25), and then the pairs of numbers to be multiplied (in a list separated by spaces or commas");
  Serial.setTimeout(5000); // max time allowed between serial inputs
}

void loop()
 {
  int numOfMults = 0;                             // number of pairs to multiply
  int *numArray;                                // pointer to beginning of array memory block
  numArray = (int *)malloc(sizeof(int)*50);   // dynamically allocate an array that can hold up to 50 floats 

  numOfMults = Serial.parseInt(); // take in the number of multiplications from user
  Serial.println(numOfMults);
  // take in the specified amount of numbers (2 times the num of multiplications) in format: 1,2,3...
  // then convert that into an array of floats, where every 2 indices
  // is a pair of numbers to multiply
  for (int i = 0; i < (2*numOfMults) ;i++)
    {
      numArray[i] = Serial.parseInt();
    } 
      multNums(numOfMults,numArray);  // call function to get the product of all the numbers 

      delay(5000);                    // wait 5 seconds before starting the loop again
 }
 
void multNums(int numofNums,int nums[])
{
  int *productArray;                                 // pointer to beginning of the product array memory block
  productArray = (int *)malloc(sizeof(int)*25);    // dynamically allocate an array that can hold up to 25 floats (for the products)

  // multiply all the number pairs in the array, store the product in another
  for(int i=0;i<(2*numofNums);i+2)
  {
      productArray[i/2] = nums[i]*nums[i+1];         // multiply current number pair, store in the product array one index at a time 
  }
  // print the products
  for(int i=0; i < sizeof(productArray) ;i++)
  {
    Serial.println(productArray[i]);
  }
}

I thought my approach would work, but I believe that there is something I am doing with the serial input that is causing the code not work (although there could be some other issue). I also wonder if maybe it's because I'm running this in Tinkercad and not the real Arduino IDE. Any help would be greatly appreciated.

So run it in Wokwi.

It doesn't work there either, so I assume it's my code, and likely the way I'm using parseInt and parseFloat. This time it just prints out the first number the user enters, and not even the other ones. I'm just not sure what else to do besides reading everything in one byte at a time (like assembly), and then casting it to integers.

Post a link to the wokwi. You can get one using the share button there.

Print out the numbers to be multiplied to confirm you have read in the numbers to multiply.

a7

It looks like it's reading in the numbers correctly, and it's not reading in more than it's supposed to. (after I typed in 6.0 I tried to type in 7.0 and it didn't print on the screen, so I assume that's a good sign).

Why are you using dynamic memory allocation?

Because otherwise I'd have to manually allocate space, and some may be wasted. Generally I don't like to hardcode in values for arrays. If that's what's causing issues I'd be happy to not dynamically allocate it.

I know a lot of people like to user buffers of characters and then convert them to numbers, I would do that in assembly, but in C/C++ I am used to dynamically allocating memory like this or using some other data structure.

there's various issues. one bug is the following -- i+2

but i think using parseInt() when there may be no input can rapidly get out of sync

consider the following the first demonstrates that multNums() works. you'll need to figure out how to use parseInt(), be patient, it doesn't return for 5 seconds.

get this to work and then worry about malloc

#define N 50
int numArray  [N] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int prodArray [N];


void multNums (int numofNums, int nums[])
{
    for (int i = 0; i < numofNums; i++)  {
        prodArray [i] = nums [i] * nums [i+1];
        Serial.println (prodArray [i]);
    }
}

void setup ()
{
    Serial.begin (9600);
    Serial.println ("Enter the number of Multiplications (up to 25), and then the pairs of numbers to be multiplied (in a list separated by spaces or commas");
    Serial.setTimeout (5000);

    multNums (10, numArray);
}

void loop ()
{
    if (! Serial.available ())
        return;

    int numOfMults = Serial.parseInt ();
    Serial.println (numOfMults);

    int *numArray = (int *)malloc (sizeof (int)*50);

    for (int i = 0; i < (2*numOfMults); i++) {
        numArray[i] = Serial.parseInt ();
    }
    multNums (numOfMults,numArray);
}
  for (int i=0; i < numofNums; i + 2)

Bzzzt!

  for (int i=0; i < numofNums; i += 2)

At least. What a horrible little program.

Lotsa confusion about half and twice. sizeof in bytes of a float array. &c.

a7

I changed it to 2*numofNums because it was obviously wrong, but that still hasn't fixed it. I also changed the sizeof() in the last for loop to just explicitly be the number of products in the array.

Works. Sorta.

// I heavily modified the original code, because Arduino provides functions
// which parse the serial input for you, thus not requiring the manual checking
// for newline characters, casting data types, dealing with things 1 byte at a time, etc.

void setup() 
{
  Serial.begin(9600);
  Serial.println("Enter the number of Multiplications (up to 25), and then the pairs of numbers to be multiplied (in a list separated by spaces or commas");
  Serial.setTimeout(7000); // max time allowed between serial inputs
}

void loop()
 {
  int numOfMults = 0;                             // number of pairs to multiply
  float *numArray;                                // pointer to beginning of array memory block
  numArray = (float *)malloc(sizeof(float)*50);   // dynamically allocate an array that can hold up to 50 floats 

  numOfMults = Serial.parseInt(); // take in the number of multiplications from user

  Serial.println(numOfMults);
// for (;;);
  // take in the specified amount of numbers (2 times the num of multiplications) in format: 1,2,3...
  // then convert that into an array of floats, where every 2 indices
  // is a pair of numbers to multiply
  for (int i = 0; i < (2*numOfMults) ;i++)
    {
      numArray[i] = Serial.parseFloat();
      Serial.println(numArray[i]);
    } 
      multNums(numOfMults * 2,numArray);  // call function to get the product of all the numbers 

      delay(5000);                    // wait 5 seconds before starting the loop again
 }
 
void multNums(int numofNums,float nums[])
{
//  float *productArray;                                 // pointer to beginning of the product array memory block
//  productArray = (float *)malloc(sizeof(float)*numofNums);    // dynamically allocate an array that can hold up to 25 floats (for the products)

float productArray[50];


  Serial.print("size of productArray ");
  Serial.println(sizeof(productArray));

  Serial.print("numofNums");
  Serial.println(numofNums);

  // multiply all the number pairs in the array, store the product in another
  for(int i=0;i<numofNums;i+=2)
  {

Serial.print("                   i ");
Serial.println(i);

  Serial.print("nums[i] ");
  Serial.println(nums[i]);

  Serial.print("nums[i + 1] ");
  Serial.println(nums[i + 1]);


      productArray[i/2] = nums[i]*nums[i+1];         // multiply current number pair, store in the product array one index at a time 


  Serial.print("product ");
  Serial.println(productArray[i/2]);



  }

Serial.println("WTF");

  // print the products
  for(int i=0; i < numofNums / 2 ;i++)
  {
    Serial.println(productArray[i]);
  }
}

That's all printing I added that maybe you could have to see what the values of key variables are and if they are properly informing the flow of the code.

WTF showed me your infinite loop for examples.

a7

All I had to do was add the += 2 to part to my for loop and it fixed it. Thanks! I am kicking myself for not seeing that.

Plus the "obviously wrong" thing. At least.

And

I also changed the sizeof()

because it was wrong.

a7

Yup, I can't believe I didn't catch that. I used to be much better at C, but after 2 years of doing Machine learning stuff in Python every day I have forgotten a lot of key stuff about normal languages.

If it makes it any better, I wrote this in 30 min at around 4:30 am last night before I went to bed :slight_smile:

Wasted? On a tiny machine like an MCU, you have to be fully aware of the memory limit. Whether it's unused heap space, or unused buffer space, really makes no difference. Arguably, pre-allocated buffers are safer because they are declared at compile time and thus their maximum size is precisely known. Not so, dynamic memory. You never called 'free()' that I can see, so it amounts to a static allocation, but is more complex.

I've done worse fully rested and sober, so.

a7

It would have been kind to us, to review the code the next day before posting it in the forum.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.