[#20036] Re: Roundoff problem with Float and Marshal — matz@... (Yukihiro Matsumoto)

まつもと ゆきひろです

16 messages 2003/04/18
[#20045] Re: Roundoff problem with Float and Marshal — nobu.nakada@... 2003/04/20

なかだです。

[#20063] Re: Roundoff problem with Float and Marshal — matz@... (Yukihiro Matsumoto) 2003/04/22

まつもと ゆきひろです

[#20097] jcode.rb — akira yamada / やまだあきら <akira@...>

25 messages 2003/04/26
[#20098] Re: jcode.rb — matz@... (Yukihiro Matsumoto) 2003/04/27

まつもと ゆきひろです

[#20105] Re: jcode.rb — WATANABE Hirofumi <eban@...> 2003/04/28

わたなべです。

[#20108] Re: jcode.rb — matz@... (Yukihiro Matsumoto) 2003/04/28

まつもと ゆきひろです

[ruby-dev:20012] radix from 2 through 36

From: nobu.nakada@...
Date: 2003-04-11 10:05:33 UTC
List: ruby-dev #20012
なかだです。

[ruby-talk:69145](のサブジェクト)を見て、なんとなくString#to_i
とInteger#to_sの基数に2から36まで使えるようにしてみました。使い
途があるかないのかよく分かりませんが。


Index: bignum.c
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/bignum.c,v
retrieving revision 1.89
diff -u -2 -p -r1.89 bignum.c
--- bignum.c	9 Apr 2003 06:49:51 -0000	1.89
+++ bignum.c	11 Apr 2003 09:52:23 -0000
@@ -376,15 +376,20 @@ rb_cstr_to_inum(str, base, badcheck)
 	}
 	break;
+      case 3:
+	len = 2;
+	break;
       case 8:
-	len = 3;
 	if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
 	    str += 2;
 	}
+      case 4: case 5: case 6: case 7:
+	len = 3;
 	break;
       case 10:
-	len = 4;
 	if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
 	    str += 2;
 	}
+      case 11: case 12: case 13: case 14: case 15:
+	len = 4;
 	break;
       case 16:
@@ -394,4 +399,15 @@ rb_cstr_to_inum(str, base, badcheck)
 	}
 	break;
+      default:
+	if (base < 2 || 36 < base) {
+	    rb_raise(rb_eArgError, "illegal radix %d", base);
+	}
+	if (base <= 32) {
+	    len = 5;
+	}
+	else {
+	    len = 6;
+	}
+	break;
     }
     if (*str == '0') {		/* squeeze preceeding 0s */
@@ -408,8 +424,5 @@ rb_cstr_to_inum(str, base, badcheck)
 	    if (end == str) goto bad; /* no number */
 	    while (*end && ISSPACE(*end)) end++;
-	    if (*end) {		      /* trailing garbage */
-	      bad:
-		rb_invalid_str(s, "Integer");
-	    }
+	    if (*end) goto bad;	      /* trailing garbage */
 	}
 
@@ -435,30 +448,5 @@ rb_cstr_to_inum(str, base, badcheck)
     for (i=len;i--;) zds[i]=0;
     while (c = *str++) {
-	switch (c) {
-	  case '8': case '9':
-	    if (base == 8) {
-		c = base;
-		break;
-	    }
-	  case '0': case '1': case '2': case '3': case '4':
-	  case '5': case '6': case '7': 
-	    c = c - '0';
-	    nondigit = 0;
-	    break;
-	  case 'a': case 'b': case 'c':
-	  case 'd': case 'e': case 'f':
-	    c -= 'a' - 'A';
-	  case 'A': case 'B': case 'C':
-	  case 'D': case 'E': case 'F':
-	    if (base != 16) {
-		nondigit = c;
-		c = base;
-	    }
-	    else {
-		c = c - 'A' + 10;
-		nondigit = 0;
-	    }
-	    break;
-	  case '_':
+	if (c == '_') {
 	    if (badcheck) {
 		if (nondigit) goto bad;
@@ -466,9 +454,19 @@ rb_cstr_to_inum(str, base, badcheck)
 	    }
 	    continue;
-	  default:
-	    c = base;
+	}
+	else if (isdigit(c)) {
+	    c -= '0';
+	}
+	else if (islower(c)) {
+	    c -= 'a' - 10;
+	}
+	else if (isupper(c)) {
+	    c -= 'A' - 10;
+	}
+	else {
 	    break;
 	}
 	if (c >= base) break;
+	nondigit = 0;
 	i = 0;
 	num = c;
@@ -490,5 +488,8 @@ rb_cstr_to_inum(str, base, badcheck)
 	if (s+1 < str && str[-1] == '_') goto bad;
 	while (*str && ISSPACE(*str)) str++;
-	if (*str) goto bad;
+	if (*str) {
+	  bad:
+	    rb_invalid_str(s, "Integer");
+	}
     }
 
@@ -599,5 +600,5 @@ rb_str2inum(str, base)
 }
 
-static char hexmap[] = "0123456789abcdef";
+static const char digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 VALUE
 rb_big2str(x, base)
@@ -618,23 +619,34 @@ rb_big2str(x, base)
 	return rb_str_new2("0");
     }
-    if (base == 10) {
-	j = (SIZEOF_BDIGITS/sizeof(char)*CHAR_BIT*i*241L)/800+2;
-	hbase = 10000;
-    }
-    else if (base == 16) {
-	j = (SIZEOF_BDIGITS/sizeof(char)*CHAR_BIT*i)/4+2;
-	hbase = 0x10000;
-    }
-    else if (base == 8) {
-	j = (SIZEOF_BDIGITS/sizeof(char)*CHAR_BIT*i)+2;
-	hbase = 010000;
-    }
-    else if (base == 2) {
-	j = (SIZEOF_BDIGITS*CHAR_BIT*i)+2;
-	hbase = 020;
-    }
-    else {
+    j = SIZEOF_BDIGITS*CHAR_BIT*i;
+    switch (base) {
+      case 2: break;
+      case 3:
+	j = j * 647L / 1024;
+	break;
+      case 4: case 5: case 6: case 7:
+	j /= 2;
+	break;
+      case 8: case 9:
+	j /= 3;
+	break;
+      case 10: case 11: case 12: case 13: case 14: case 15:
+	j = j * 241L / 800;
+	break;
+      case 16: case 17: case 18: case 19: case 20: case 21:
+      case 22: case 23: case 24: case 25: case 26: case 27:
+      case 28: case 29: case 30: case 31:
+	j /= 4;
+	break;
+      case 32: case 33: case 34: case 35: case 36:
+	j /= 5;
+	break;
+      default:
 	rb_raise(rb_eArgError, "illegal radix %d", base);
+	break;
     }
+    j += 2;
+    hbase = base * base;
+    hbase *= hbase;
 
     t = rb_big_clone(x);
@@ -657,5 +669,5 @@ rb_big2str(x, base)
 	while (k--) {
 	    c = (char)(num % base);
-	    s[--j] = hexmap[(int)c];
+	    s[--j] = digitmap[(int)c];
 	    num /= base;
 	    if (i == 0 && num == 0) break;
Index: numeric.c
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/numeric.c,v
retrieving revision 1.76
diff -u -2 -p -r1.76 numeric.c
--- numeric.c	11 Apr 2003 06:37:48 -0000	1.76
+++ numeric.c	11 Apr 2003 08:33:12 -0000
@@ -1174,4 +1174,5 @@ fix_uminus(num)
 }
 
+static const char digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 VALUE
 rb_fix2str(x, base)
@@ -1179,19 +1180,27 @@ rb_fix2str(x, base)
     int base;
 {
-    char fmt[4], buf[22], *b = buf;
+    char buf[SIZEOF_LONG/2 + 2], *b = buf + sizeof b;
     long val = FIX2LONG(x);
+    int neg = 0;
 
-    fmt[0] = '%'; fmt[1] = 'l'; fmt[3] = '\0';
-    if (base == 10) fmt[2] = 'd';
-    else if (base == 16) fmt[2] = 'x';
-    else if (base == 8) fmt[2] = 'o';
-    else rb_raise(rb_eArgError, "illegal radix %d", base);
+    if (base < 2 || 36 < base) {
+	rb_raise(rb_eArgError, "illegal radix %d", base);
+    }
+    if (val == 0) {
+	return rb_str_new2("0");
+    }
     if (val < 0) {
 	val = -val;
-	*b++ = '-';
+	neg = 1;
+    }
+    *--b = '\0';
+    do {
+	*--b = digitmap[(int)(val % base)];
+    } while (val /= base);
+    if (neg) {
+	*--b = '-';
     }
 
-    sprintf(b, fmt, val);
-    return rb_str_new2(buf);
+    return rb_str_new2(b);
 }
 
Index: string.c
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/string.c,v
retrieving revision 1.149
diff -u -2 -p -r1.149 string.c
--- string.c	26 Mar 2003 18:26:45 -0000	1.149
+++ string.c	11 Apr 2003 08:53:39 -0000
@@ -1837,10 +1837,4 @@ rb_str_to_i(argc, argv, str)
     else base = NUM2INT(b);
 
-    switch (base) {
-      case 0: case 2: case 8: case 10: case 16:
-	break;
-      default:
-	rb_raise(rb_eArgError, "illegal radix %d", base);
-    }
     return rb_str_to_inum(str, base, Qfalse);
 }


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread

Prev Next