Browse Source

Added a second ndigits precision parameter to the round method

Marco Bambini 7 years ago
parent
commit
e558a9d90c
2 changed files with 42 additions and 2 deletions
  1. 37 0
      src/optionals/gravity_math.c
  2. 5 2
      src/shared/gravity_value.h

+ 37 - 0
src/optionals/gravity_math.c

@@ -630,6 +630,43 @@ static bool math_round (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, u
     }
 
     if (VALUE_ISA_FLOAT(value)) {
+        // check for extra parameter
+        gravity_int_t ndigits = 0;
+        if (nargs == 3 && VALUE_ISA_INT(GET_VALUE(2))) {
+            gravity_value_t extra = GET_VALUE(2);
+            if (VALUE_AS_INT(extra) > 0) ndigits = VALUE_AS_INT(extra);
+            if (ndigits > FLOAT_MAX_DECIMALS) ndigits = FLOAT_MAX_DECIMALS;
+        }
+        
+        if (ndigits) {
+            double d = pow(10.0, (double)ndigits);
+            gravity_float_t f = (gravity_float_t)(ROUND((gravity_float_t)value.f * (gravity_float_t)d)) / (gravity_float_t)d;
+            
+            // convert f to string
+            char buffer[512];
+            snprintf(buffer, sizeof(buffer), "%f", f);
+            
+            // trunc c string to the requested ndigits
+            char *p = buffer;
+            while (p) {
+                if (p[0] == '.') {
+                    ++p;
+                    gravity_int_t n = 0;
+                    while (p && n < ndigits) {
+                        ++p;
+                        ++n;
+                    }
+                    if (p) p[0] = 0;
+                    break;
+                }
+                ++p;
+            }
+            
+            // re-convert string to float
+            RETURN_VALUE(VALUE_FROM_FLOAT(strtod(buffer, NULL)), rindex);
+        }
+        
+        // simpler round case
         gravity_float_t computed_value = (gravity_float_t)ROUND((gravity_float_t)value.f);
         RETURN_VALUE(VALUE_FROM_FLOAT(computed_value), rindex);
     }

+ 5 - 2
src/shared/gravity_value.h

@@ -66,8 +66,8 @@
 extern "C" {
 #endif
 
-#define GRAVITY_VERSION						"0.5.4"     // git tag 0.5.4
-#define GRAVITY_VERSION_NUMBER				0x000504    // git push --tags
+#define GRAVITY_VERSION						"0.5.5"     // git tag 0.5.4
+#define GRAVITY_VERSION_NUMBER				0x000505    // git push --tags
 #define GRAVITY_BUILD_DATE                  __DATE__
 
 #ifndef GRAVITY_ENABLE_DOUBLE
@@ -158,15 +158,18 @@ extern "C" {
 
 // MARK: - STRUCT -
 
+// FLOAT_MAX_DECIMALS FROM https://stackoverflow.com/questions/13542944/how-many-significant-digits-have-floats-and-doubles-in-java
 #if GRAVITY_ENABLE_DOUBLE
 typedef double                              gravity_float_t;
 #define FLOAT_MAX                           DBL_MAX
 #define FLOAT_MIN                           DBL_MIN
+#define FLOAT_MAX_DECIMALS                  16
 #define FLOAT_EPSILON                       0.00001
 #else
 typedef float                               gravity_float_t;
 #define FLOAT_MAX                           FLT_MAX
 #define FLOAT_MIN                           FLT_MIN
+#define FLOAT_MAX_DECIMALS                  7
 #define FLOAT_EPSILON                       0.00001
 #endif