Duvida em Codigo

Oii,tou este server mas não está calculando direito alguem me pode ajudar


O primeiro grande problema que eu identifiquei

Você não inicializou a variável n e isso afeta esta linha:

double x[n], y[n];

Pois não dá pra saber que tamanho x e y teria, poderia ser até mesmo 0.

E afeta também seus loops, porque você coloca i < n, então eles nunca executam.

Então sua primeira correção deve ser inicializar a variavel x.

E isso nos leva ao próximo grande erro que é o fato de que os arrays x e y também não foram inicializados.

Com base nas observações acima eu modifiquei sua função, ficou assim:


void *linearregression(void *arg) {
  int *newsockfd = (int *)arg;
  string string1(buffer);
  string string2(previousBuffer);

  int n = 5;
  double x[n] = {1, 2, 4, 3, 5};
  double y[n] = {1, 3, 3, 2, 5};
  double xsum = 0, x2sum = 0, ysum = 0, xysum = 0;

  for (int i = 0; i < n; i++) {
    cout << "x[" << i << "] = ";
    cout << "y[" << i << "] = ";
  }

  for (int i = 0; i < n; i++) {
    xsum = xsum + x[i];            // calculate sigma(xi)
    ysum = ysum + y[i];            // calculate sigma(yi)
    x2sum = x2sum + pow(x[i], 2);  // calculate sigma(x^2i)
    xysum = xysum + x[i] * y[i];   // calculate sigma(xi*yi)
  }

  double b = (n * xysum - xsum * ysum) / (n * x2sum - xsum * xsum);
  double a = (ysum - b * xsum) / n;

  cout << "\nCalculated value of a is " << a << "and b is " << b << '\n';
  cout << "Equation of best fit is: y = " << a << " + " << b << " x";

  return NULL;
}

Eu compilei com este comando:

g++ main.cpp -lpthread && ./a.out

E testei usando curl com esse comando:

curl http://localhost:65432

E o resultado foi esse:

GET / HTTP/1.1
Host: localhost:65432
User-Agent: curl/7.65.3
Accept: */*


x[0] = y[0] = x[1] = y[1] = x[2] = y[2] = x[3] = y[3] = x[4] = y[4] = 
Calculated value of a is 0.4and b is 0.8
Equation of best fit is: y = 0.4 + 0.8 x n
*******************************************************************************

Eu fiquei na dúvida em 2 coisas:

Dúvidas 1: Pra quê serve o loop abaixo?

for (int i = 0; i < n; i++) {
  cout << "x[" << i << "] = ";
  cout << "y[" << i << "] = ";
}

Dúvidas 2: Eu usei o valor 5 para n e uns valores quaisquer pra x e y, mas de onde virão esses valores na verdade?

1 curtida

Muito obrigada por me ajudar

Eu acho que encontrei a solução. No caso vc passaria os valores de x e y através da URL.

Por exemplo, no navegador, vc acessaria este endereço:

http://localhost:65432/?x=1,10.56,3,434.300&y=3,3,4.5,12.3

Percebeu que os valores são separados por uma virgula?

Dá pra acessar pela linha de comando também usando o curl assim:

curl "http://localhost:65432?x=1,2,3,4&y=3,3,4.5,12.3"

O código abaixo foi compilado com o seguinte comando:

g++ main.cpp -Wall -Wextra -Wpedantic -lpthread

Veja como ficou:

#include <netinet/in.h>
#include <pthread.h>
#include <sys/socket.h>
#include <unistd.h>

#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <regex>
#include <string>

int client;

void error(const char *message) {
  perror(message);
  exit(EXIT_FAILURE);
}

void pargeArg(const char *arg, std::vector<double> &x, std::vector<double> &y) {
  std::string str((const char *)arg);
  std::smatch m;
  std::regex r("([xy])=([0-9,.]+)");

  while (std::regex_search(str, m, r)) {
    auto &curr = m[1] == "x" ? x : y;
    std::stringstream ss(m[2]);
    std::string substr;

    while (std::getline(ss, substr, ',')) curr.push_back(std::stod(substr));

    str = m.suffix().str();
  }
}

void *test(void *arg) {
  std::vector<double> x;
  std::vector<double> y;

  pargeArg((const char *)arg, x, y);

  int n = x.size();
  double xsum = 0, x2sum = 0, ysum = 0, xysum = 0;

  for (int i = 0; i < n; i++) {
    xsum = xsum + x[i];            // calculate sigma(xi)
    ysum = ysum + y[i];            // calculate sigma(yi)
    x2sum = x2sum + pow(x[i], 2);  // calculate sigma(x^2i)
    xysum = xysum + x[i] * y[i];   // calculate sigma(xi*yi)
  }

  double b = (n * xysum - xsum * ysum) / (n * x2sum - xsum * xsum);
  double a = (ysum - b * xsum) / n;

  std::string response("HTTP/1.1 200 OK\n\nCalculated value of A is: " +
                       std::to_string(a) + " and B is: " + std::to_string(b) +
                       "\n"
                       "Equation of best fit is: y = " +
                       std::to_string(a) + " + " + std::to_string(b) + "x\n");

  send(client, response.c_str(), response.length(), 0);
  std::cout << response << std::endl;

  return NULL;
}

int main() {
  constexpr int PORT = 65432;
  constexpr int SIZE = 1024;
  char buffer[SIZE];
  pthread_t s;
  sockaddr_in addrIn = {AF_INET, htons(PORT), INADDR_ANY, 0};
  sockaddr *addr = (sockaddr *)&addrIn;
  socklen_t addrlen = sizeof(addrIn);
  const int server = socket(AF_INET, SOCK_STREAM, 0);
  const int optName = SO_REUSEADDR | SO_REUSEPORT;
  const int opt = 1;
  const socklen_t len = sizeof(opt);

  if (server == 0) error("socket failed");
  if (setsockopt(server, SOL_SOCKET, optName, &opt, len)) error("setsockopt");
  if (bind(server, addr, addrlen) < 0) error("Bind failed");
  if (listen(server, 3) < 0) error("listen");

  while (true) {
    if ((client = accept(server, addr, &addrlen)) < 0) error("accept");
    read(client, buffer, SIZE);
    pthread_create(&s, NULL, test, buffer);
    pthread_join(s, NULL);
    close(client);
  }

  close(server);
  return 0;
}
2 curtidas

g++ main.cpp -Wall -Wextra -Wpedantic

Eu usei as opção -Wall -Wextra -Wpedantic na hora de compilar apenas para me certificar de que o código estava correto. Vc pode compilar com o comando que vc mostrou normalmente.

Vc nem chegou a testar o código que mostrei antes de falar que não é compativel e saber se funciona?

Imagino que os valores de x e y venha de uma lugar, como vc não deu maiores detalhes, eu escrevi o código considerando que esses valores viriam da URL, mas isso pode ser facilmente alterado.

Por favor, me explique detalhadamente de onde vem os valores de x e y.

Aqui já seria outro problema. Se vc quer salvar os dados, vc pode criar um arquivo de texto simples contendo os valores.

Sim

O programa 7-regression é o cliente? Vc poderia me mostrar o código fonte dele?

Sim

Acho que entendi.

Eu rodei o cliente com o seguinte comando:

 ./7-regression localhost 1000

E parece que deu, olha como ficou:

#include <netinet/in.h>
#include <pthread.h>
#include <sys/socket.h>
#include <unistd.h>

#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <regex>
#include <string>

constexpr int PORT = 65432;
std::vector<double> x;
std::vector<double> y;

void error(const char *message) {
  perror(message);
  exit(EXIT_FAILURE);
}

void pargeArg(const char *arg, std::vector<double> &x, std::vector<double> &y) {
  std::string str(arg);
  std::size_t comma = str.find(',');
  x.push_back(std::stod(str.substr(0, comma)));
  y.push_back(std::stod(str.substr(comma + 1)));
}

void *linearregression(void *arg) {
  pargeArg((const char *)arg, x, y);

  const int n = x.size();
  double xsum = 0, x2sum = 0, ysum = 0, xysum = 0;

  for (int i = 0; i < n; i++) {
    xsum = xsum + x[i];            // calculate sigma(xi)
    ysum = ysum + y[i];            // calculate sigma(yi)
    x2sum = x2sum + pow(x[i], 2);  // calculate sigma(x^2i)
    xysum = xysum + x[i] * y[i];   // calculate sigma(xi*yi)
  }

  double b = (n * xysum - xsum * ysum) / (n * x2sum - xsum * xsum);
  double a = (ysum - b * xsum) / n;

  std::string response("Calculated value of A is: " + std::to_string(a) +
                       " and B is: " + std::to_string(b) +
                       "\n"
                       "Equation of best fit is: y = " +
                       std::to_string(a) + " + " + std::to_string(b) + "x\n");

  std::cout << response << std::endl;

  return NULL;
}

int main() {
  constexpr int SIZE = 1024;
  char buffer[SIZE];
  std::cout << "Started..." << std::endl;
  pthread_t s;
  sockaddr_in addrIn = {AF_INET, htons(PORT), INADDR_ANY, 0};
  sockaddr *addr = (sockaddr *)&addrIn;
  socklen_t addrlen = sizeof(addrIn);
  int server, client;
  const int optName = SO_REUSEADDR | SO_REUSEPORT;
  const int opt = 1;
  const socklen_t len = sizeof(opt);

  if ((server = socket(AF_INET, SOCK_STREAM, 0)) == 0) error("socket failed");
  if (setsockopt(server, SOL_SOCKET, optName, &opt, len)) error("setsockopt");
  if (bind(server, addr, addrlen) < 0) error("Bind failed");
  if (listen(server, 3) < 0) error("listen");

  if ((client = accept(server, addr, &addrlen)) < 0) error("accept");

  while (read(client, buffer, SIZE) > 0) {
    pthread_create(&s, NULL, linearregression, buffer);
    pthread_join(s, NULL);
  }

  close(client);
  close(server);

  return 0;
}
1 curtida