浏览代码

Add print options to biginteger and bigdecimal.
Move helper into the src dir since it shouldn't be exported.

Sam Jaffe 4 年之前
父节点
当前提交
a700e39648

+ 2 - 0
bigdecimal.xcodeproj/project.pbxproj

@@ -75,6 +75,7 @@
 		CD5FB2801F06EF7D005A0D61 /* biginteger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = biginteger.cpp; sourceTree = "<group>"; };
 		CD5FB2861F06EFEA005A0D61 /* libbigdecimal.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libbigdecimal.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		CD8176CC25C5A4100043E7E7 /* include */ = {isa = PBXFileReference; lastKnownFileType = folder; path = include; sourceTree = "<group>"; };
+		CD8176D325C5A6B50043E7E7 /* bignum_helper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bignum_helper.h; sourceTree = "<group>"; };
 		CDB7F52D20B19D3F0053645C /* bignumber_test_printers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bignumber_test_printers.h; sourceTree = "<group>"; };
 		CDB7F52E20B19E0D0053645C /* bignumber_test_printers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bignumber_test_printers.cpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
@@ -144,6 +145,7 @@
 			children = (
 				CD5FB2801F06EF7D005A0D61 /* biginteger.cpp */,
 				CD2EC1BE1F0AF3B800D49DF5 /* bigdecimal.cpp */,
+				CD8176D325C5A6B50043E7E7 /* bignum_helper.h */,
 				CD2EC1C41F0BCCBF00D49DF5 /* bignum_helper.cpp */,
 			);
 			path = src;

+ 3 - 1
include/math/number_format.h

@@ -10,6 +10,8 @@
 
 namespace math {
 
-struct number_format {};
+struct number_format {
+  bool separate_thousands;
+};
 
 }

+ 3 - 2
src/bigdecimal.cpp

@@ -6,10 +6,11 @@
 //
 
 #include "math/bigdecimal.h"
-#include "math/bignum_helper.h"
 
 #include <cstdlib>
 
+#include "bignum_helper.h"
+
 using namespace math;
 
 static int32_t add_scale(int32_t scale) {
@@ -291,5 +292,5 @@ std::string bigdecimal::to_string(number_format fmt) const {
   } else if (data.back()) {
     sprintf(ptr, "%0.*d", hidden, 0);
   }
-  return output.data();
+  return detail::apply(fmt, output.data());
 }

+ 3 - 2
src/biginteger.cpp

@@ -6,12 +6,13 @@
 //
 
 #include "math/biginteger.h"
-#include "math/bignum_helper.h"
 
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
 
+#include "bignum_helper.h"
+
 using namespace math;
 
 static void read(int32_t & dst, char const *& str, size_t len) {
@@ -206,5 +207,5 @@ std::string biginteger::to_string(number_format fmt) const {
   for (size_t i = data.size() - 1; i > 0; --i, idx += SEG_DIGITS) {
     sprintf(output.data() + idx, "%0.*d", SEG_DIGITS, data[i - 1]);
   }
-  return output.data();
+  return detail::apply(fmt, output.data());
 }

+ 14 - 2
src/bignum_helper.cpp

@@ -5,11 +5,11 @@
 //  Created by Sam Jaffe on 7/4/17.
 //
 
-#include "math/bignum_helper.h"
+#include "bignum_helper.h"
 
 #include <cmath>
 
-using namespace math::detail;
+#include "math/number_format.h"
 
 namespace {
 constexpr int32_t const MAX_SEG{999999999};
@@ -149,4 +149,16 @@ data_type divide(data_type & remainder, data_type const & divisor) {
   } while (compare(remainder, divisor) >= 0);
   return accum;
 }
+
+std::string apply(number_format const & fmt, std::string text) {
+  if (fmt.separate_thousands) {
+    constexpr std::size_t const LEN_THOUSAND{3};
+    auto pos = std::min(text.size(), text.find('.'));
+    for (pos -= LEN_THOUSAND; pos > LEN_THOUSAND; pos -= LEN_THOUSAND) {
+      text.insert(pos, ",");
+    }
+    if (pos) { text.insert(pos, ","); }
+  }
+  return text;
+}
 }}

+ 7 - 0
include/math/bignum_helper.h

@@ -7,8 +7,13 @@
 
 #pragma once
 
+#include <string>
 #include <vector>
 
+namespace math {
+struct number_format;
+}
+
 namespace math { namespace detail {
 using data_type = std::vector<int32_t>;
 constexpr const int32_t powers[] = {1,      10,      100,      1000,      10000,
@@ -20,4 +25,6 @@ void subtract_nounderflow(data_type & rhs, data_type const & lhs,
                           size_t offset = 0);
 void multiply(data_type & rhs, data_type const & lhs);
 data_type divide(data_type & remainder, data_type const & divisor);
+
+std::string apply(number_format const & fmt, std::string text);
 }}

+ 6 - 0
test/bigdecimal_test.cpp

@@ -17,6 +17,12 @@ TEST(BigDecimalTest, ConstructDecimal) {
               "1000.0000000001");
 }
 
+TEST(BigDecimalTest, FormatsWithCommaOnlyBeforeDecimal) {
+  math::number_format fmt{.separate_thousands = true};
+  EXPECT_THAT(math::bigdecimal("1000000.0000000001").to_string(fmt),
+              "1,000,000.0000000001");
+}
+
 TEST(BigDecimalTest, ConstructIntWithScaleAndStep) {
   EXPECT_THAT(math::bigdecimal(1000000000, -2).to_string(), "1000000000");
 }