Changeset 979


Ignore:
Timestamp:
07/08/20 01:53:39 (4 years ago)
Author:
Maciej Komosinski
Message:

Improved float-rounding functions, follow-up to r970

Location:
cpp/common
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpp/common/nonstd_math.cpp

    r970 r979  
    44
    55#include "nonstd_math.h"
    6 #ifdef USE_PRINTFLOAT_DRAGON4
    76#include <PrintFloat/PrintFloat.h>
    8 #else
    97#include <sstream>
    10 #endif
     8#include <algorithm>    // std::min
    119
    1210RandomGenerator &rndGetInstance()
     
    1614}
    1715
     16std::string doubleToString(double x, int precision)
     17{
     18        std::stringstream ss;
     19        ss << std::fixed;
     20        ss.precision(precision); //set the number of places after decimal
     21        ss << x;
     22        return ss.str();
     23}
     24
    1825int doubleToString(double x, int precision, char *buffer, int bufferlen)
    1926{
     27        // C++ in 2020 and the impossible challenge https://stackoverflow.com/questions/277772/avoid-trailing-zeroes-in-printf
     28        if (precision < 0)
     29        {
     30                // The "g" format does not allow to use the number of decimal places after the decimal point. Dragon4 on the other hand fills in unnecessary trailinig zeros... so both are good only for "full precision".
    2031#ifdef USE_PRINTFLOAT_DRAGON4
    21         return PrintFloat64(buffer, bufferlen, x,
    22                 ((x < -1e17) || (x > 1e17) || ((x < 1e-4) && (x > -1e-4) && (x != 0.0)))
    23                 ? PrintFloatFormat_Scientific : PrintFloatFormat_Positional,
    24                 precision); //http://www.ryanjuckett.com/programming/printing-floating-point-numbers/
     32                return PrintFloat64(buffer, bufferlen, x,
     33                        ((x < -1e17) || (x > 1e17) || ((x < 1e-4) && (x > -1e-4) && (x != 0.0)))
     34                        ? PrintFloatFormat_Scientific : PrintFloatFormat_Positional,
     35                        precision); //http://www.ryanjuckett.com/programming/printing-floating-point-numbers/
    2536#else
    26         char format[10];
    27         sprintf(format, "%%.%dg", precision < 0 ? 17 : precision); //https://stackoverflow.com/questions/16839658/printf-width-specifier-to-maintain-precision-of-floating-point-value
    28         return sprintf(buffer, format, x);
     37                return sprintf(buffer, "%.17g", x);
    2938#endif
     39        }
     40        else
     41        {
     42                std::string s = doubleToString(x, precision);
     43                strncpy(buffer, s.c_str(), std::min(bufferlen, (int)s.length() + 1));
     44                buffer[bufferlen - 1] = 0; //ensure the string is truncated
     45                return s.length();
     46        }
    3047}
    3148
     
    3350double round(const double x, const int precision)
    3451{
    35 #ifdef USE_PRINTFLOAT_DRAGON4
    36         char buffer[30];
    37         doubleToString(x, precision, buffer, 30);
    38         double rounded = strtod(buffer, NULL);
    39 #else
    40         std::stringstream ss;
    41         ss << std::fixed;
    42         ss.precision(precision); // set the number of places after decimal
    43         ss << x;
    44         double rounded = stod(ss.str());
    45 #endif
     52        double rounded = std::stod(doubleToString(x, precision));
    4653        //printf("%d  %20g \t %20g\n", precision, x, rounded); //for debugging
    4754        return rounded;
  • cpp/common/nonstd_math.h

    r970 r979  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2019  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    3535int doubleToString(double x, int precision, char *buffer, int bufferlen);
    3636
     37#include <string>
     38std::string doubleToString(double x, int precision);
    3739double round(const double x, const int precision);
    3840
Note: See TracChangeset for help on using the changeset viewer.