# More precise Bignum#to\_f

**URL:** <https://www.ruby-forum.com/t/more-precise-bignum-to-f/133518>\
**Category:** Development\
**Created:** [April 1, 2008, 8:44am UTC](https://www.ruby-forum.com/t/more-precise-bignum-to-f/133518 "2008-04-01T08:44:10Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![nobu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e9c0ed/32.png) [@nobu](https://www.ruby-forum.com/u/nobu)\
**Post date:** [April 1, 2008, 8:44am UTC](https://www.ruby-forum.com/t/more-precise-bignum-to-f/133518/1 "2008-04-01T08:44:10Z")

</div>

e$B$J$+$@$G$9!#e(B

e$B$A$g$C$HIbF0\>.?tE@4X78e(B(e$B@53N$K$O4]$a4X78e(B)e$B$r8+D\>$7$F$$$?$H$3$m!"e(B  
[2007-07-28](http://d.hatena.ne.jp/hnw/20070728) e$B$NLdBj$,%j%F%i%k0J30$G$OD\>$Ce(B  
e$B$F$$$J$$$3$H$K5$$E$-$^$7$?!#e(B

e$B0J2\<$N%Q%C%A$G$O!"?te(B%e$B$+$ie(B10%e$B6/DxEYCY$/$J$k$h$&$G$9!#e(B

x=2**53+1  
a = []  
a.concat (0…33).map{|i|[(x \<\< i) + 1, (x+1) \<\< i]}  
x=2**23+1  
a.concat (7…33).map{|i|[(x \<\< i) + 1, (x \<\< i) + 1]}

a.each {|i,j| p i unless i.to\_f==j}  
t0 = Process.times  
100000.times{a.each{|i,j| i.to\_f}}  
printf “%10.6f\n”, Process.times.utime-t0.utime

# Index: bignum.c

— bignum.c (revision 15877)  
+++ bignum.c (working copy)  
@@ -1134,13 +1134,62 @@ rb\_dbl2big(double d)  
}

+static int  
+nlz(BDIGIT x)  
+{

- BDIGIT y;
- int n = BITSPERDIG;  
+#if BITSPERDIG \> 64
- y = x \>\> 64; if (y) {n -= 64; x = y;}  
+#endif  
+#if BITSPERDIG \> 32
- y = x \>\> 32; if (y) {n -= 32; x = y;}  
+#endif  
+#if BITSPERDIG \> 16
- y = x \>\> 16; if (y) {n -= 16; x = y;}  
+#endif
- y = x \>\> 8; if (y) {n -= 8; x = y;}
- y = x \>\> 4; if (y) {n -= 4; x = y;}
- y = x \>\> 2; if (y) {n -= 2; x = y;}
- y = x \>\> 1; if (y) {return n - 2;}
- return n - x;  
+}
- 

static double  
big2dbl(VALUE x)  
{  
double d = 0.0;

- long i = RBIGNUM\_LEN(x);
- BDIGIT \*ds = BDIGITS(x);

- long i = RBIGNUM\_LEN(x), lo = 0, bits;
- BDIGIT \*ds = BDIGITS(x), dl;

- while (i–) {
- d = ds[i] + BIGRAD\*d;

- if (i) {
- bits = i \* BITSPERDIG - nlz(ds[i-1]);
- if (bits \> DBL\_MANT\_DIG+DBL\_MAX\_EXP) {
- 

```
 d = HUGE_VAL;

```

- }
- else {
- 

```
 if (bits > DBL_MANT_DIG+1)

```

- lo = (bits -= DBL\_MANT\_DIG+1) / BITSPERDIG;
- 

```
 else

```

- bits = 0;
- 

```
 while (--i > lo) {

```

- d = ds[i] + BIGRAD\*d;
- 

```
 }

```

- 

```
 dl = ds[i];

```

- 

```
 if (bits && (dl & (1UL << (bits %= BITSPERDIG)))) {

```

- int carry = dl & ~(~0UL \<\< bits);
- if (!carry) {
- 

```
   while (i-- > 0) {

```

- 

```
 if ((carry = ds[i]) != 0) break;

```

- 

```
   }

```

- }
- if (carry) {
- 

```
   dl &= ~0UL << bits;

```

- 

```
   dl += 1UL << bits;

```

- 

```
   if (!dl) d += 1;

```

- }
- 

```
 }

```

- 

```
 d = dl + BIGRAD*d;

```

- 

```
 if (lo) d = ldexp(d, lo * BITSPERDIG);

```

- }  
}  
if (!RBIGNUM\_SIGN(x)) d = -d;

---

<div class="post-metadata">

**Author:** ![nobu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e9c0ed/32.png) [@nobu](https://www.ruby-forum.com/u/nobu)\
**Post date:** [April 1, 2008, 9:01am UTC](https://www.ruby-forum.com/t/more-precise-bignum-to-f/133518/2 "2008-04-01T09:01:55Z")

</div>

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:34195] more precise Bignum#to\_f”  
on Tue, 1 Apr 2008 15:43:33 +0900, Nobuyoshi N.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

|e$B$A$g$C$HIbF0\>.?tE@4X78e(B(e$B@53N$K$O4]$a4X78e(B)e$B$r8+D\>$7$F$$$?$H$3$m!“e(B  
|[http://d.hatena.ne.jp/hnw/20070728](http://d.hatena.ne.jp/hnw/20070728) e$B$NLdBj$,%j%F%i%k0J30$G$OD\>$Ce(B  
|e$B$F$$$J$$$3$H$K5$$E$-$^$7$?!#e(B  
|  
|e$B0J2\<$N%Q%C%A$G$O!”?te(B%e$B$+$ie(B10%e$B6/DxEYCY$/$J$k$h$&$G$9!#e(B

e$B%3%\_%C%H$7$F$/$@$5$$!#e(B
