Advertisement
Korotkodul

C++_line

Sep 7th, 2024 (edited)
838
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.57 KB | None | 0 0
  1. // Read data of an experiment from file given as command line argument and
  2. // having the following format:
  3. //   x1 y1
  4. //   ...
  5. //   xN yN
  6. // Compute linear regression [y = a + b*x] coefficients using the least
  7. // squares method.
  8.  
  9. #include <cmath>
  10. #include <fstream>
  11. #include <iostream>
  12. #include <iterator>
  13. #include <stdexcept>
  14. #include <string>
  15. #include <tuple>
  16. #include <vector>
  17.  
  18. struct Point
  19. {
  20.   double x, y;
  21.  
  22.   Point() = default;
  23.  
  24.   Point(double xx, double yy) : x{xx}, y{yy}
  25.   { /* empty body */
  26.   }
  27. };
  28.  
  29. std::istream& operator>> (std::istream& is, Point& rhs)
  30. {
  31.   return is >> rhs.x >> rhs.y;
  32. }
  33.  
  34. std::ostream& operator<< (std::ostream& os, const Point& rhs)
  35. {
  36.   return os << rhs.x << " " << rhs.y;
  37. }
  38.  
  39. auto read (const std::string& filename)
  40. {
  41.   std::ifstream ifs{filename};
  42.   if (!ifs)
  43.     throw std::runtime_error{"can't open file '" + filename + "'"};
  44.  
  45.   return std::vector<Point>{std::istream_iterator<Point>{ifs},
  46.                             std::istream_iterator<Point>{}};
  47. }
  48.  
  49. struct Coeff
  50. {
  51.   double value;  // coefficient estimate
  52.   double delta;  // confidence band
  53.  
  54.   Coeff(double v, double d) : value{v}, delta{d}
  55.   { /* empty body */
  56.   }
  57. };
  58.  
  59. bool cmp(Point one, Point two, double a, double b) {
  60.   double done = pow(one.y - a * one.x - b, 2.0);
  61.   double dtwo = pow(two.y - a * two.x - b, 2.0);
  62.   return done < dtwo;
  63. }
  64.  
  65. auto least_squares (const std::vector<Point>& points)
  66. {
  67.   // compute average values
  68.   size_t N = points.size();
  69.   double x_ave = 0., x2_ave = 0.;
  70.   double y_ave = 0., xy_ave = 0.;
  71.  
  72.   for (const auto& p : points)
  73.   {
  74.     x_ave += p.x;
  75.     x2_ave += p.x * p.x;
  76.     y_ave += p.y;
  77.     xy_ave += p.x * p.y;
  78.   }
  79.   x_ave /= N;
  80.   x2_ave /= N;
  81.   y_ave /= N;
  82.   xy_ave /= N;
  83.  
  84.   // compute linear coefficient estimate
  85.   double b = (xy_ave - x_ave * y_ave) / (x2_ave - x_ave * x_ave);
  86.  
  87.   if (!std::isfinite(b))
  88.     throw std::overflow_error{"division by zero"};
  89.  
  90.   // compute constant coefficient estimate
  91.   double a = y_ave - b * x_ave;
  92.  
  93.  
  94.  
  95.   return std::make_tuple(Coeff{a, 0.}, Coeff{b, 0.});
  96. }
  97.  
  98. int main (int argc, char* argv[])
  99. {
  100.   if (argc != 2)
  101.   {
  102.     std::cerr << "usage: " << argv[0] << "  file_with_data" << std::endl;
  103.     return 2;
  104.   }
  105.  
  106.   try
  107.   {
  108.     std::string datafile{argv[1]};
  109.  
  110.     auto [a, b] = least_squares(read(datafile));  // C++17
  111.  
  112.     std::cout << datafile << "  " << a.value << " " << a.delta << "  "
  113.               << b.value << " " << b.delta << std::endl;
  114.   }
  115.   catch (std::exception& e)
  116.   {
  117.     std::cerr << "error: " << e.what() << std::endl;
  118.     return 1;
  119.   }
  120. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement