@@ -197,7 +197,8 @@ class DecimalUtilOp {
197197 number += ' 0' ;
198198 }
199199 } else {
200- number += digits.substr (0 , exponent) + ' .' + digits.substr (exponent + 1 , digits.length ());
200+ number += digits.substr (0 , exponent) + ' .' +
201+ digits.substr (exponent + 1 , digits.length ());
201202 }
202203 return number;
203204 }
@@ -221,30 +222,38 @@ class DecimalUtilOp {
221222 return value;
222223 }
223224
224- inline static double roundUp (double value, int decimalPlaces) {
225- const double multiplier = std::pow (10.0 , decimalPlaces);
226- return std::ceil (value * multiplier) / multiplier;
225+ // Round double to certain precision with half up.
226+ inline static double roundTo (double value, int precision) {
227+ int charsNeeded = 1 + snprintf (NULL , 0 , " %.*f" , (int )precision, value);
228+ char * buffer = reinterpret_cast <char *>(malloc (charsNeeded));
229+ double nextValue;
230+ if (value < 0 ) {
231+ nextValue = nextafter (value, value - 0.1 );
232+ } else {
233+ nextValue = nextafter (value, value + 0.1 );
234+ }
235+ snprintf (buffer, charsNeeded, " %.*f" , (int )precision, nextValue);
236+ return atof (buffer);
227237 }
228238
229239 // return unscaled value and scale
230240 inline static std::pair<std::string, uint8_t > splitVarChar (
231- const StringView& value, int toScale) {
241+ const StringView& value,
242+ int toScale) {
232243 std::string s = getNormalNumber (value.str ());
233244 size_t pos = s.find (' .' );
234245 if (pos == std::string::npos) {
235246 return {s.substr (0 , pos), 0 };
236- } else if (toScale < scales .length ()) {
237- // If toScale is less than scales.length(), the string scales will be cut and rounded.
238- std::string roundedValue = std::to_string ( roundUp ( std::stod (s), toScale));
239- std::string scales = roundedValue. substr (pos + 1 , roundedValue. length ( ));
240- return {
241- roundedValue.substr (0 , pos) + scales,
242- scales.length ()};
247+ } else if (toScale < s .length () - pos - 1 ) {
248+ // If toScale is less than scales.length(), the string scales will be cut
249+ // and rounded.
250+ std::string roundedValue = std::to_string ( roundTo ( std::stod (s), toScale ));
251+ pos = roundedValue. find ( ' . ' );
252+ std::string scales = roundedValue.substr (pos + 1 , toScale);
253+ return {roundedValue. substr ( 0 , pos) + scales, scales.length ()};
243254 } else {
244255 std::string scales = s.substr (pos + 1 , s.length ());
245- return {
246- s.substr (0 , pos) + scales,
247- scales.length ()};
256+ return {s.substr (0 , pos) + scales, scales.length ()};
248257 }
249258 }
250259
0 commit comments