In [1]:
#include <cmath>
#include <iostream>
#include <limits>

using namespace std;


Out[1]:


In [2]:
double epsilon = numeric_limits<double>::epsilon();


Out[2]:
(double) 0.000000

In [3]:
double x[2] = {1, 1};


Out[3]:
(double [2]) { 1.000000, 1.000000 }

In [5]:
double normNaive(double* x) {
    double normSquared = 0;
    for (int i = 0; i < 2; i++)
        normSquared += x[i] * x[i];
    return sqrt(normSquared);
}


Out[5]:


In [6]:
cout << normNaive(x) << endl;


1.41421
Out[6]:
(std::__1::basic_ostream &) @0x7fffcfcfa660

In [7]:
double normBetter(double* x, int n) {
    double maxElement = epsilon;
    double normSquared = 0;
    
    for (int i=0; i < n; i++) {
        maxElement = max(maxElement, fabs(x[i]));
    }
    
    for (int i=0; i < n; i++) {
        double scaled = x[i] / maxElement;
        normSquared += scaled * scaled;
    }
    
    return sqrt(normSquared) * maxElement;
}


Out[7]:


In [8]:
cout << normBetter(x, 2) << endl;


1.41421
Out[8]:
(std::__1::basic_ostream &) @0x7fffcfcfa660

In [9]:
normBetter(x, 2);


Out[9]:
(double) 1.414214

In [20]:
normBetter((double[3]){1,2,3}, 3);


Out[20]:
(double) 3.741657

In [18]:
normBetter((double[4]){1,2,3,4}, 4);


Out[18]:
(double) 5.477226

In [ ]: