lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] odd/1e24-vs-1e24L b11d029: Extended precision and fl


From: Greg Chicares
Subject: [lmi-commits] [lmi] odd/1e24-vs-1e24L b11d029: Extended precision and floating literals of type double
Date: Mon, 19 Mar 2018 18:07:01 -0400 (EDT)

branch: odd/1e24-vs-1e24L
commit b11d0298502696fe0ff8ed72b05dce13f714e611
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Extended precision and floating literals of type double
    
    log10(10^24)/3.0 equals 8, but truncating that 8 seemed to make it 7.
    See:
      https://lists.nongnu.org/archive/html/lmi/2018-03/msg00080.html
---
 sandbox_test.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/sandbox_test.cpp b/sandbox_test.cpp
index 0ed05ae..0ef72a3 100644
--- a/sandbox_test.cpp
+++ b/sandbox_test.cpp
@@ -23,8 +23,95 @@
 
 #include "test_tools.hpp"
 
+#include <cmath>                        // floor(), log10()
+
+#include <iomanip>
+#include <ios>
+#include <sstream>
+#include <string>
+
+template<typename T>
+std::string floating_rep(T t)
+{
+    std::ostringstream oss;
+    oss << std::hex << std::setfill('0');
+    int realsize = sizeof(T);
+#if defined __GNUC__
+    if(12 == realsize) realsize = 10;
+#endif // defined __GNUC__
+    unsigned char const* u = reinterpret_cast<unsigned char const*>(&t);
+    for(int j = realsize - 1; 0 <= j; --j)
+        oss << std::setw(2) << static_cast<int>(u[j]);
+    return oss.str();
+}
+
 int test_main(int, char*[])
 {
+    std::cout
+        << "Unsurprisingly, log10(10^24)/3.0 equals 8,"
+        << "\nbut truncating that 8 in any of several ways makes it 7:"
+        << "\n" << std::endl
+        ;
+    double const xyzzy = 999'999'999'999'999.0;
+    double const a = std::log10(xyzzy);
+    double const b = a / 3.0;
+    double const c = std::floor(b);
+    double const d = std::trunc(b);
+    double const e = static_cast<int>(b);
+    std::cout << "a: " << a << " ; b: " << b << " ; c: " << c << std::endl;
+    std::cout << "a: " << a << ' ' << floating_rep(a) << std::endl;
+    std::cout << "b: " << b << ' ' << floating_rep(b) << std::endl;
+    std::cout << "c: " << c << ' ' << floating_rep(c) << std::endl;
+    std::cout << "d: " << d << ' ' << floating_rep(d) << std::endl;
+    std::cout << "e: " << e << ' ' << floating_rep(e) << std::endl;
+
+    {
+    std::cout
+        << "\nThat seemed to be an excess-precision problem;"
+        << "\nyet it still occurs with type 'long double'"
+        << "\n(but the hex representation of that 8 looks weird):"
+        << "\n" << std::endl
+        ;
+    long double const t = 1'000'000'000'000'000'000'000'000.0;
+    long double const x =           (std::log10(t) / 3.0);
+    long double const y = std::trunc(std::log10(t) / 3.0);
+    std::cout << "x: " << x << ' ' << floating_rep(x) << std::endl;
+    std::cout << "y: " << y << ' ' << floating_rep(y) << std::endl;
+    }
+    {
+    std::cout
+        << "\nIt still occurs with even with 'long double' C functions"
+        << "\n(notably using log10l() instead of log10()):"
+        << "\n" << std::endl
+        ;
+    long double const t = 1'000'000'000'000'000'000'000'000.0;
+    long double const u = 1'000'000'000'000'000'000'000'000.0L;
+    long double const x =            (   log10l(t) / 3.0);
+    long double const y =      truncl(   log10l(t) / 3.0);
+    std::cout << "t: " << t << ' ' << floating_rep(t) << std::endl;
+    std::cout << "u: " << u << ' ' << floating_rep(u) << std::endl;
+    std::cout << "x: " << x << ' ' << floating_rep(x) << std::endl;
+    std::cout << "y: " << y << ' ' << floating_rep(y) << std::endl;
+    }
+    {
+    std::cout
+        << "\nThe explanation is that 10^24 is inexact: everything"
+        << "\nseems to work as hoped if all arithmetic is performed"
+        << "\nin long double precision, with long double library"
+        << "\nfunctions, on a long double value initialized from"
+        << "\na long double floating literal:"
+        << "\n" << std::endl
+        ;
+    long double const t = 1'000'000'000'000'000'000'000'000.0;
+    long double const u = 1'000'000'000'000'000'000'000'000.0L;
+    long double const x =            (   log10l(u) / 3.0);
+    long double const y =      truncl(   log10l(u) / 3.0);
+    std::cout << "t: " << t << ' ' << floating_rep(t) << std::endl;
+    std::cout << "u: " << u << ' ' << floating_rep(u) << std::endl;
+    std::cout << "x: " << x << ' ' << floating_rep(x) << std::endl;
+    std::cout << "y: " << y << ' ' << floating_rep(y) << std::endl;
+    }
+
     return 0;
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]