Refactor standard deviation function

Standard deviation doesn't have a measurement unit, thus it would make
sense to always return a floating point value.
Update the function signature and reorganize the code to improve
readability, though not changing the implementation.

Bug: 195113227
Test: manual
Signed-off-by: Alessio Balsini <balsini@google.com>
Change-Id: I7dabdcbbd84583cf9882f4edf7b898b96cccd465
diff --git a/include/ditto/statistics.h b/include/ditto/statistics.h
index d7bada1..2ef552d 100644
--- a/include/ditto/statistics.h
+++ b/include/ditto/statistics.h
@@ -26,6 +26,6 @@
 timespec StatisticsGetMax(const std::vector<timespec>& time_samples);
 timespec StatisticsGetMean(const std::vector<timespec>& time_samples);
 timespec StatisticsGetMedian(const std::vector<timespec>& time_samples);
-timespec StatisticsGetSd(const std::vector<timespec>& time_samples);
+double StatisticsGetSd(const std::vector<timespec>& time_samples);
 
 }  // namespace dittosuite
diff --git a/src/result.cpp b/src/result.cpp
index b06f6c7..07795a5 100644
--- a/src/result.cpp
+++ b/src/result.cpp
@@ -47,7 +47,7 @@
   max_ = StatisticsGetMax(time_samples_);
   mean_ = StatisticsGetMean(time_samples_);
   median_ = StatisticsGetMedian(time_samples_);
-  sd_ = StatisticsGetSd(time_samples_);
+  sd_ = NsToTimespec(StatisticsGetSd(time_samples_));
 }
 
 std::string Result::ComputeNextInstructionPath(const std::string& instruction_path) {
diff --git a/src/statistics.cpp b/src/statistics.cpp
index 8b28ecd..2bb770b 100644
--- a/src/statistics.cpp
+++ b/src/statistics.cpp
@@ -59,22 +59,23 @@
   }
 }
 
-// TODO(lucialup): improve readability
-// the standard deviation is computed as the square root of the
-// variance given by the deviation of each point relative to the mean
-// SD = sqrt( variance ),
-// where variance = Sum( (point_i - mean)^2 ) / total_number_of_points
-timespec StatisticsGetSd(const std::vector<timespec>& time_samples) {
-  int64_t mean = TimespecToNs(StatisticsGetMean(time_samples));
-  int64_t result(0), deviation_pow;
-  int64_t deviation;
-  for (const auto& time_sample : time_samples) {
-    deviation = TimespecToNs(time_sample) - mean;
-    deviation_pow = std::pow(deviation, 2);
-    result += deviation_pow;  // TODO(lucialup): add overflow error handling
+// The standard deviation sd of a population of N samples, where x_i is the
+// i-th sample and x is the average among all the samples is computed as:
+//
+// sd = sqrt( sum( (x_i - x)^2 ) / N )
+double StatisticsGetSd(const std::vector<timespec>& samples) {
+  double mean = TimespecToNs(StatisticsGetMean(samples));
+  double variance;
+
+  variance = 0.0;
+  for (const auto& s : samples) {
+    double deviation = TimespecToNs(s) - mean;
+    double deviation_square = std::pow(deviation, 2);
+    variance += deviation_square;  // TODO(lucialup): add overflow error handling
   }
-  int time_samples_size = time_samples.size();
-  return NsToTimespec(std::sqrt(result / time_samples_size));
+  variance /= samples.size();
+
+  return std::sqrt(variance);
 }
 
 }  // namespace dittosuite