Skip to content

Commit fabdcad

Browse files
committed
fix #444: Fix precision when converting double to string
1 parent 43e6f0b commit fabdcad

File tree

2 files changed

+74
-9
lines changed

2 files changed

+74
-9
lines changed

include/scratchcpp/value.h

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <limits>
88
#include <ctgmath>
99
#include <cassert>
10+
#include <iomanip>
1011
#include <utf8.h>
1112

1213
#include "global.h"
@@ -40,7 +41,7 @@ class LIBSCRATCHCPP_EXPORT Value
4041
Value(float numberValue) :
4142
m_type(Type::Double)
4243
{
43-
m_doubleValue = numberValue;
44+
m_doubleValue = floatToDouble(numberValue);
4445
}
4546

4647
/*! Constructs a number Value. */
@@ -376,7 +377,7 @@ class LIBSCRATCHCPP_EXPORT Value
376377
m_stringValue.~basic_string();
377378

378379
m_type = Type::Double;
379-
m_doubleValue = v;
380+
m_doubleValue = floatToDouble(v);
380381
return *this;
381382
}
382383

@@ -943,7 +944,7 @@ class LIBSCRATCHCPP_EXPORT Value
943944
static std::string doubleToString(double v)
944945
{
945946
std::stringstream stream;
946-
stream << v;
947+
stream << std::setprecision(std::max(16u, digitCount(v))) << v;
947948
std::string s = stream.str();
948949
std::size_t index;
949950

@@ -961,6 +962,33 @@ class LIBSCRATCHCPP_EXPORT Value
961962

962963
return s;
963964
}
965+
966+
static double floatToDouble(float v)
967+
{
968+
unsigned int digits = digitCount(v);
969+
double f = std::pow(10, digits);
970+
return std::round(v * f) / f;
971+
}
972+
973+
template<typename T>
974+
static unsigned int digitCount(T v)
975+
{
976+
const T epsilon = 0.0000001;
977+
T intpart;
978+
unsigned int i = 1, j = 0;
979+
980+
if (std::abs(std::modf(v, &intpart)) >= epsilon) {
981+
T tmp_intpart;
982+
983+
while (std::abs(std::modf(v * std::pow(10, i), &tmp_intpart)) >= epsilon)
984+
i++;
985+
}
986+
987+
while (std::abs(intpart / pow(10, j)) >= 1.0)
988+
j++;
989+
990+
return i + j;
991+
}
964992
};
965993

966994
} // namespace libscratchcpp

test/scratch_classes/value_test.cpp

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ TEST(ValueTest, DefaultConstructor)
2020
TEST(ValueTest, FloatConstructor)
2121
{
2222
Value v(3.14f);
23-
ASSERT_EQ(v.toDouble(), 3.14f);
23+
ASSERT_EQ(v.toDouble(), 3.14);
2424
ASSERT_EQ(v.type(), Value::Type::Double);
2525
ASSERT_FALSE(v.isInfinity());
2626
ASSERT_FALSE(v.isNegativeInfinity());
@@ -385,7 +385,7 @@ TEST(ValueTest, FloatAssignment)
385385
{
386386
Value v;
387387
v = 3.14f;
388-
ASSERT_EQ(v.toDouble(), 3.14f);
388+
ASSERT_EQ(v.toDouble(), 3.14);
389389
ASSERT_EQ(v.type(), Value::Type::Double);
390390
ASSERT_FALSE(v.isInfinity());
391391
ASSERT_FALSE(v.isNegativeInfinity());
@@ -930,12 +930,12 @@ TEST(ValueTest, ToDouble)
930930
v = 2.54;
931931
ASSERT_EQ(v.toDouble(), 2.54);
932932
v = 2.54f;
933-
ASSERT_EQ(v.toDouble(), 2.54f);
933+
ASSERT_EQ(v.toDouble(), 2.54);
934934

935935
v = -2.54;
936936
ASSERT_EQ(v.toDouble(), -2.54);
937937
v = -2.54f;
938-
ASSERT_EQ(v.toDouble(), -2.54f);
938+
ASSERT_EQ(v.toDouble(), -2.54);
939939

940940
v = false;
941941
ASSERT_EQ(v.toDouble(), 0.0);
@@ -1164,6 +1164,20 @@ TEST(ValueTest, ToString)
11641164
ASSERT_EQ(v.toString(), "-999999999999999999");
11651165
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
11661166

1167+
v = 2.0;
1168+
ASSERT_EQ(v.toString(), "2");
1169+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1170+
v = 2.0f;
1171+
ASSERT_EQ(v.toString(), "2");
1172+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1173+
1174+
v = -2.0;
1175+
ASSERT_EQ(v.toString(), "-2");
1176+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1177+
v = -2.0f;
1178+
ASSERT_EQ(v.toString(), "-2");
1179+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1180+
11671181
v = 2.54;
11681182
ASSERT_EQ(v.toString(), "2.54");
11691183
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
@@ -1178,6 +1192,29 @@ TEST(ValueTest, ToString)
11781192
ASSERT_EQ(v.toString(), "-2.54");
11791193
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
11801194

1195+
v = 2550.625021000115;
1196+
ASSERT_EQ(v.toString(), "2550.625021000115");
1197+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1198+
1199+
v = 2550.625021000115f;
1200+
ASSERT_EQ(v.toString(), "2550.625");
1201+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1202+
1203+
v = -2550.625021000115;
1204+
ASSERT_EQ(v.toString(), "-2550.625021000115");
1205+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1206+
1207+
v = -2550.625021000115f;
1208+
ASSERT_EQ(v.toString(), "-2550.625");
1209+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1210+
1211+
v = 0.001;
1212+
ASSERT_EQ(v.toString(), "0.001");
1213+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1214+
v = -0.001;
1215+
ASSERT_EQ(v.toString(), "-0.001");
1216+
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
1217+
11811218
v = false;
11821219
ASSERT_EQ(v.toString(), "false");
11831220
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
@@ -1214,10 +1251,10 @@ TEST(ValueTest, ToString)
12141251
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
12151252

12161253
v = "9432.4e+6";
1217-
ASSERT_EQ(v.toString(), "9.4324e+9");
1254+
ASSERT_EQ(v.toString(), "9432400000");
12181255
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
12191256
v = "-9432.4e+6";
1220-
ASSERT_EQ(v.toString(), "-9.4324e+9");
1257+
ASSERT_EQ(v.toString(), "-9432400000");
12211258
ASSERT_EQ(utf8::utf16to8(v.toUtf16()), v.toString());
12221259

12231260
v = "false";

0 commit comments

Comments
 (0)