mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #4225 from shuujii/improve-compatibility-to-cruby-for-float-to_s
Improve compatibility to CRuby for `Float#to_s`
This commit is contained in:
+44
-4
@@ -10,6 +10,7 @@
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mruby.h>
|
||||
#include <mruby/array.h>
|
||||
@@ -23,9 +24,9 @@
|
||||
#define floor(f) floorf(f)
|
||||
#define ceil(f) ceilf(f)
|
||||
#define fmod(x,y) fmodf(x,y)
|
||||
#define MRB_FLO_TO_STR_FMT "%.8g"
|
||||
#define FLO_TO_STR_PREC 8
|
||||
#else
|
||||
#define MRB_FLO_TO_STR_FMT "%.16g"
|
||||
#define FLO_TO_STR_PREC 16
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -177,10 +178,49 @@ num_div(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
flo_to_s(mrb_state *mrb, mrb_value flt)
|
||||
{
|
||||
if (isnan(mrb_float(flt))) {
|
||||
mrb_float f = mrb_float(flt);
|
||||
|
||||
if (isinf(f)) {
|
||||
return f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
|
||||
: mrb_str_new_lit(mrb, "Infinity");
|
||||
}
|
||||
else if (isnan(f)) {
|
||||
return mrb_str_new_lit(mrb, "NaN");
|
||||
}
|
||||
return mrb_float_to_str(mrb, flt, MRB_FLO_TO_STR_FMT);
|
||||
else {
|
||||
char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
|
||||
mrb_value str = mrb_float_to_str(mrb, flt, fmt);
|
||||
mrb_int len;
|
||||
char *begp;
|
||||
|
||||
insert_dot_zero:
|
||||
begp = RSTRING_PTR(str);
|
||||
len = RSTRING_LEN(str);
|
||||
for (char *p = begp, *endp = p + len; p < endp; ++p) {
|
||||
if (*p == '.') {
|
||||
return str;
|
||||
}
|
||||
else if (*p == 'e') {
|
||||
ptrdiff_t e_pos = p - begp;
|
||||
mrb_str_cat(mrb, str, ".0", 2);
|
||||
p = RSTRING_PTR(str) + e_pos;
|
||||
memmove(p + 2, p, len - e_pos);
|
||||
memcpy(p, ".0", 2);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
if (FLO_TO_STR_PREC + (begp[0] == '-') <= len) {
|
||||
--fmt[sizeof(fmt) - 3]; /* %.16g(%.8g) -> %.15g(%.7g) */
|
||||
str = mrb_float_to_str(mrb, flt, fmt);
|
||||
goto insert_dot_zero;
|
||||
}
|
||||
else {
|
||||
mrb_str_cat(mrb, str, ".0", 2);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
/* 15.2.9.3.2 */
|
||||
|
||||
@@ -41,6 +41,10 @@ mrb_open_core(mrb_allocf f, void *ud)
|
||||
|
||||
mrb_init_core(mrb);
|
||||
|
||||
#if !defined(MRB_DISABLE_STDIO) && defined(_MSC_VER) && _MSC_VER < 1900
|
||||
_set_output_format(_TWO_DIGIT_EXPONENT);
|
||||
#endif
|
||||
|
||||
return mrb;
|
||||
}
|
||||
|
||||
|
||||
@@ -206,4 +206,37 @@ assert('Float#>>') do
|
||||
assert_equal(-1, -23.0 >> 128)
|
||||
end
|
||||
|
||||
assert('Float#to_s') do
|
||||
uses_float = 4e38.infinite? # enable MRB_USE_FLOAT?
|
||||
|
||||
assert_equal("Infinity", Float::INFINITY.to_s)
|
||||
assert_equal("-Infinity", (-Float::INFINITY).to_s)
|
||||
assert_equal("NaN", Float::NAN.to_s)
|
||||
assert_equal("0.0", 0.0.to_s)
|
||||
assert_equal("-0.0", -0.0.to_s)
|
||||
assert_equal("-3.21", -3.21.to_s)
|
||||
assert_equal("50.0", 50.0.to_s)
|
||||
assert_equal("0.00021", 0.00021.to_s)
|
||||
assert_equal("-0.00021", -0.00021.to_s)
|
||||
assert_equal("2.1e-05", 0.000021.to_s)
|
||||
assert_equal("-2.1e-05", -0.000021.to_s)
|
||||
assert_equal("1.0e+20", 1e20.to_s)
|
||||
assert_equal("-1.0e+20", -1e20.to_s)
|
||||
assert_equal("1.0e+16", 10000000000000000.0.to_s)
|
||||
assert_equal("-1.0e+16", -10000000000000000.0.to_s)
|
||||
assert_equal("100000.0", 100000.0.to_s)
|
||||
assert_equal("-100000.0", -100000.0.to_s)
|
||||
if uses_float
|
||||
assert_equal("1.0e+08", 100000000.0.to_s)
|
||||
assert_equal("-1.0e+08", -100000000.0.to_s)
|
||||
assert_equal("1.0e+07", 10000000.0.to_s)
|
||||
assert_equal("-1.0e+07", -10000000.0.to_s)
|
||||
else
|
||||
assert_equal("1.0e+15", 1000000000000000.0.to_s)
|
||||
assert_equal("-1.0e+15", -1000000000000000.0.to_s)
|
||||
assert_equal("100000000000000.0", 100000000000000.0.to_s)
|
||||
assert_equal("-100000000000000.0", -100000000000000.0.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
end # const_defined?(:Float)
|
||||
|
||||
Reference in New Issue
Block a user