aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--object.c10
-rw-r--r--test/ruby/test_float.rb12
-rw-r--r--test/ruby/test_string.rb3
-rw-r--r--util.c29
5 files changed, 46 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index bb3f451b12..51d375a4d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Thu Apr 1 13:24:12 2010 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * object.c (rb_cstr_to_dbl): return 0.0 if hexadecimal and
+ baccheck is FALSE: Float("0x1p+0") works, but "0x1p+0".to_f
+ doesn't. [ruby-dev:40650]
+
+ * util.c (ruby_strtod): allow hexdecimal integers.
+
Thu Apr 1 13:20:50 2010 NARUSE, Yui <naruse@ruby-lang.org>
* lib/scanf.rb: support %a format. [ruby-dev:40650]
diff --git a/object.c b/object.c
index cdcd287016..4fc4b6a759 100644
--- a/object.c
+++ b/object.c
@@ -2246,6 +2246,11 @@ rb_cstr_to_dbl(const char *p, int badcheck)
if (!p) return 0.0;
q = p;
while (ISSPACE(*p)) p++;
+
+ if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ return 0.0;
+ }
+
d = strtod(p, &end);
if (errno == ERANGE) {
OutOfRange();
@@ -2284,6 +2289,11 @@ rb_cstr_to_dbl(const char *p, int badcheck)
}
*n = '\0';
p = buf;
+
+ if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ return 0.0;
+ }
+
d = strtod(p, &end);
if (errno == ERANGE) {
OutOfRange();
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index c18e4f0422..3e5b1177c0 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -87,6 +87,18 @@ class TestFloat < Test::Unit::TestCase
assert_raise(ArgumentError){Float("1__1")}
# add expected behaviour here.
assert_equal(10, Float("1_0"))
+
+ assert_equal([ 0.0].pack('G'), [Float(" 0x0p+0").to_f].pack('G'))
+ assert_equal([-0.0].pack('G'), [Float("-0x0p+0").to_f].pack('G'))
+ assert_equal(255.0, Float("0Xff"))
+ assert_equal(255.5, Float("0Xff.8"))
+ assert_equal(1.0, Float("0X1.P+0"))
+ assert_equal(1024.0, Float("0x1p10"))
+ assert_equal(1024.0, Float("0x1p+10"))
+ assert_equal(0.0009765625, Float("0x1p-10"))
+ assert_equal(2.6881171418161356e+43, Float("0x1.3494a9b171bf5p+144"))
+ assert_equal(-3.720075976020836e-44, Float("-0x1.a8c1f14e2af5dp-145"))
+
end
def test_divmod
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 9dd3ea90ce..c5b86fa177 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1398,7 +1398,10 @@ class TestString < Test::Unit::TestCase
assert_equal([-0.0].pack('G'), [S("-0.0").to_f].pack('G'))
assert_equal([ 0.0].pack('G'), [S(" 0x0p+0").to_f].pack('G'))
assert_equal([-0.0].pack('G'), [S("-0x0p+0").to_f].pack('G'))
+ assert_equal(255.0, S("0Xff").to_f)
+ assert_equal(255.5, S("0Xff.8").to_f)
assert_equal(1.0, S("0X1.P+0").to_f)
+ assert_equal(1024.0, S("0x1p10").to_f)
assert_equal(1024.0, S("0x1p+10").to_f)
assert_equal(0.0009765625, S("0x1p-10").to_f)
assert_equal(2.6881171418161356e+43, S("0x1.3494a9b171bf5p+144").to_f)
diff --git a/util.c b/util.c
index 9cdb563040..11d0272e52 100644
--- a/util.c
+++ b/util.c
@@ -2124,24 +2124,21 @@ break2:
}
}
- if (*s != 'P' && *s != 'p') {
- s = s0;
- goto ret;
+ if (*s == 'P' || *s == 'p') {
+ dsign = 0x2C - *++s; /* +: 2B, -: 2D */
+ if (abs(dsign) == 1) s++;
+ else dsign = 1;
+
+ for (nd = 0; (c = *s) >= '0' && c <= '9'; s++) {
+ nd *= 10;
+ nd += c;
+ nd -= '0';
+ }
+ dval(rv) = ldexp(adj, nd * dsign);
}
-
- dsign = 0x2C - *++s; /* +: 2B, -: 2D */
- if (abs(dsign) != 1) {
- s = s0;
- goto ret;
+ else {
+ dval(rv) = adj;
}
-
- for (nd = 0, s++; (c = *s) >= '0' && c <= '9'; s++) {
- nd *= 10;
- nd += c;
- nd -= '0';
- }
-
- dval(rv) = ldexp(adj, nd * dsign);
goto ret;
}
nz0 = 1;