Sumar producto de una matriz

Hola!

Tengo dos arrays declarados, y quiero obtener el siguiente resultado:

1 * 7000 = 7000
2 * 9000 = 18000
3 * 5000 = 15000
4 * 11000 = 44000
5 * 10000 = 50000
6 * 13000 = 78000
** TOTAL SUMA valores = 212000**

He declarado la variable sumXY como long, pero parece que hay como un “desbordamiento” a partir del cuarto valor. Alguna idea de lo que esta pasando?

Si pongo un Serial dentro del for, lo que esta pasando allí dentro es:

7000
25000
40000
18464
2928
15392

??? Qué estoy haciendo mal?

Muchísimas gracias de antemano!

/*
  1 * 7000 = 7000
  2 * 9000 = 18000
  3 * 5000 = 15000
  4 * 11000 = 44000
  5 * 10000 = 50000
  6 * 13000 = 78000
  RESULT sumXY = 212000
*/

long n = 6;  // number of data points input so far
int x[6] = {7000, 9000, 5000, 11000, 10000, 13000};
int y[6] =  {1, 2, 3, 4, 5, 6};
long sumXY;

void setup() {
  Serial.begin(9600);
}

void loop() {

  sumXY = 0; //initialize variables to 0

  for (int i = 0; i < n; i++) {
    sumXY += x[i] * y[i]; //sum(x[i]*y[i])
  }
  Serial.println(sumXY);

  delay(10000);
}

hola te propongo que hagas una pruebas
Serial.println(sumXY, HEX);
a ver cual es el resultado y lo mismo dentro del for

Gracias por la rapidez en contestar!

El resultado ha sido el siguiente:

1B58
61A8
9C40
4820
B70
3C20
FUERA DEL LOOP:
3C20

creo que ya se!

estas comparando long n con int i dentro del for y eso no se puede hacer!!

declara n como int y me cuentas

no eso daría lugar a más iteraciones o iteraciones infinitas si falla la comparación pero no puede ser tu fallo grrr voy a encender el ordenador

Se te esta desbordando el INT (65536)

Mira:

7000 OK
25000 OK
40000 OK
18464 Tu esperas 84.000 pero te pone eso menos el limite (84.000-65536)
2928 Tu tsperas 144.000 pero te pone eso menos dos limites (144.000-65536-65536)
15392 Tu esperas 212.000 pero te pone eso menos tres limites (212.000-65536-65536-65536)

Define "x" e "y" tambien como long y te lo hara bien.

Explicacion practica, aunque quizas no muy tecnica:

El error esta en pensar que teoricamente no hay problemas porque tu cargas el dato largo en un long y no se tendria que desbordar pero no es asi.

La operacion la haces con INT y se desborda, para cuando la cargas en el LONG ya has perdido la informacion.

Te pongo este ejemplo para que lo veas mas claro:

int x = 20000;
long xlong;
int rint;
long rlong;
void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.print("valor de x: ");
  Serial.println(x);
  rint=(x+x);
  Serial.print("valor de x+x en un INT: ");
  Serial.print(rint);
  Serial.println(" SE DESBORDO");
  rlong=(x+x);
  Serial.print("valor de x+x en un LONG: ");
  Serial.print(rlong);
  Serial.println(" TAMBIEN SE DESBORDO");
  xlong=x;
  rlong=(xlong+xlong);
  Serial.print("valor de x+x en un LONG pasando previamente el valor de x a un LONG: ");
  Serial.print(rlong);
  Serial.println(" FUNCIONA !!!");
  delay(30000);
}

si puede ser eso pero no deberia pasar!

también puedes hacer para no gastar tanta ram cuando no deberia ser necesario, se transforma a long antes de multiplicar

    sumXY += (long)x[i] * (long)y[i]; //sum(x[i]*y[i])

Hola!

Ambas propuestas han funcionado, y se obtiene el resultado correcto sin “desbordaminetos”.

  1. La de GO_zalo:

int n = 6;
int x[6] = {7000, 9000, 5000, 11000, 10000, 13000};
int y[6] = {1, 2, 3, 4, 5, 6};
long sumXY;

sumXY += (long)x * (long)y*; *
2) La de cas6678:
int n = 6;
long x[6] = {7000, 9000, 5000, 11000, 10000, 13000};
long y[6] = {1, 2, 3, 4, 5, 6};
long sumXY;
sumXY += x * y*;*
Muchas gracias a los dos!!!
Un abrazo

Hola.
El problema es mas simple, define X e Y como unsigned int, porque el desbordamiento se produce al rebasar el +32767 que pasa a ser considerado como entero negativo.
Ejemplo:

/*
  1 * 7000 = 7000
  2 * 9000 = 18000
  3 * 5000 = 15000
  4 * 11000 = 44000
  5 * 10000 = 50000
  6 * 13000 = 78000
  RESULT sumXY = 212000
*/

long n = 6;  // number of data points input so far
unsigned int x[6] = {7000, 9000, 5000, 11000, 10000, 13000};
unsigned int y[6] =  {1, 2, 3, 4, 5, 6};
long sumXY;

void setup() {
  Serial.begin(9600);
}

void loop() {

  sumXY = 0; //initialize variables to 0

  for (int i = 0; i < n; i++) {
    sumXY += x[i] * y[i]; //sum(x[i]*y[i])
  }
  Serial.println(sumXY);

  delay(10000);
}

A fin de cuentas un entero con signo cubre el rango +32767 a -32768, que es ampliamente rebasado en tu ejemplo. Sin embargo un entero sin signo cubre el rango 0 a +65535 que es suficiente.

Parece que esta semana es la semana del UNSIGNED…

Alfaville. El ejemplo que has puesto esta mal. Te sugiero que copies tu codigo y lo hagas correr y nos comentes los resultados. Es verdad que en tu ejemplo el desbordamiento se produce mas tarde, pero se produce igual.

Dices que 65535 es sufucuente, al parecer no has leido ni las primeras lineas del primer mensaje donde gdconesa nos dice que quiere llegar a 212.000

Si sigo tu codigo me dara si no me equivoco 146464 (212000-65535)

Con respecto a la solucion de GO_zalo, evidentemente es mas practica que la mia porque consume muchos menos recursos, no hace que todo el array sea un long sino que solo lo convierte a long una vez (una vez por cada ciclo de for), me gusta mas.

Bueno, bueno. Que no cunda el panico.
LLevas razon, solo me he fijado en la columna “Y” y… claro no desborda.

Una oportunidad de ayudar desaprovechada.

:frowning: :frowning: :frowning: :frowning:

Esto tampoco desborda.
Casi igual que la de GO_zalo pero parece que se ejecuta mas rapido

/*
  1 * 7000 = 7000
  2 * 9000 = 18000
  3 * 5000 = 15000
  4 * 11000 = 44000
  5 * 10000 = 50000
  6 * 13000 = 78000
  RESULT sumXY = 212000
*/

long n = 6;  // number of data points input so far
unsigned int x[6] = {7000, 9000, 5000, 11000, 10000, 13000};
unsigned int y[6] =  {1, 2, 3, 4, 5, 6};
long sumXY;

void setup() {
  Serial.begin(9600);
}

void loop() {

  sumXY = 0; //initialize variables to 0

  for (int i = 0; i < n; i++) {
    sumXY += (long)(x[i] * y[i]);   //sum(x[i]*y[i])
  }
  Serial.println(sumXY);

  delay(10000);
}