e$B$J$+$@$G$9!#e(B
[ruby-talk:290296]e$B$NOC$G$9$,!"e(BBigDecimal#to_fe$B$N@:EY$,IT==J,$J$h$&$G$9!#e(B
$ ruby18 -v -rbigdecimal -e ‘printf “%.15f\n”,
BigDecimal.new(“15.25”).to_f’
ruby 1.8.6 (2008-02-08 revision 15402) [i686-linux]
15.250000000000002
$ ruby19 -v -rbigdecimal -e ‘printf “%.15f\n”,
BigDecimal.new(“15.25”).to_f’
ruby 1.9.0 (2008-02-08 revision 15402) [i686-linux]
15.250000000000002
e$BMW$9$k$Ke(B10e$B?J"*e(B2e$B?JJQ49$NLdBj$J$N$G!"e(Bstrtod()e$B$+$i;}$C$F$3$h$&$+$He(B
e$B$b;W$$$^$7$?$,!"e(Bstrtod()e$B$r$=$N$^$^;H$&$N$,0lHV4JC1$8$c$J$$$G$7$ge(B
e$B$&$+!#e(B
e$B$^$?!“e(BDBLE_FIGe$B$rFbIt$G7W;;$7$F$$$^$9$,!”%l%8%9%?4V$N1i;;$K:GE,2=e(B
e$B$5$l$?>l9g!“e(Bdoublee$B$G$O$J$/$Fe(Blong
doublee$B$G7W;;$5$l$F$7$^$&>l9g$,e(B
e$B$”$j$^$9!#e(BDBL_DIGe$B$r;H$&$Y$-$G$7$g$&!#e(B
e$B$b$&0lE@!"e(BBASEe$B$de(BBASE_FIGe$B$b<B9T;~$K5a$a$k$h$j$bDj?t$K$7$?$[$&$,$$e(B
e$B$$$N$G$O$J$$$+$H;W$$$^$9!#e(B
Index: ext/bigdecimal/bigdecimal.c
— ext/bigdecimal/bigdecimal.c (revision 15405)
+++ ext/bigdecimal/bigdecimal.c (working copy)
@@ -586,17 +586,20 @@ BigDecimal_to_f(VALUE self)
ENTER(1);
Real *p;
- double d, d2;
-
double d;
S_LONG e; -
char *buf;
GUARD_OBJ(p,GetVpValue(self,1));
if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d); -
buf = ALLOCA_N(char,(unsigned int)VpNumOfChars(p,“E”));
-
VpToString(p, buf, 0, 0);
errno = 0;
- d2 = pow(10.0,(double)e);
- if((errno == ERANGE && e>0) || (d2>1.0 && (fabs(d) > (DBL_MAX /
d2)))) {
- d = strtod(buf, 0);
- if(errno == ERANGE) {
VpException(VP_EXCEPTION_OVERFLOW,“BigDecimal to Float
conversion”,0);
if(d>0.0) return rb_float_new(DBL_MAX);
else return rb_float_new(-DBL_MAX);
}
- return rb_float_new(d*d2);
- return rb_float_new(d);
}
@@ -1051,5 +1054,5 @@ BigDecimal_remainder(VALUE self, VALUE r
{
VALUE f;
- Real *d,*rv;
- Real *d,*rv=0;
f = BigDecimal_divremain(self,r,&d,&rv);
if(f!=(VALUE)0) return f;
@@ -1505,5 +1508,5 @@ BigDecimal_to_s(int argc, VALUE *argv, V
fPlus = 2; psz++;
}
-
while(ch=*psz++) {
-
while((ch=*psz++)!=0) { if(ISSPACE(ch)) continue; if(!ISDIGIT(ch)) {
@@ -1962,4 +1965,5 @@ static U_LONG gnPrecLimit = 0; /* Globa
static U_LONG gfRoundMode = VP_ROUND_HALF_UP; /* Mode for general
rounding operation */
+#ifndef BASE_FIG
static U_LONG BASE_FIG = 4; /* =log10(BASE) /
static U_LONG BASE = 10000L; / Base value(value must be
10**BASE_FIG) /
@@ -1967,10 +1971,19 @@ static U_LONG BASE = 10000L; / Base
/* within one U_LONG. /
static U_LONG HALF_BASE = 5000L;/ =BASE/2 /
-static S_LONG DBLE_FIG = 8; / figure of double /
static U_LONG BASE1 = 1000L; / =BASE/10 /
+#else
+#ifndef BASE
+#error BASE_FIG is defined but BASE is not
+#endif
+#define HALF_BASE (BASE/2)
+#define BASE1 (BASE/10)
+#endif
+#ifndef DBLE_FIG
+#define DBLE_FIG (DBL_DIG+1) / figure of double */
+#endif
static Real VpConstOne; / constant 1.0 */
static Real VpPt5; / constant 0.5 /
-static U_LONG maxnr = 100; / Maximum iterations for calcurating
sqrt. /
+#define maxnr 100UL / Maximum iterations for calcurating sqrt. /
/ used in VpSqrt() */
@@ -2089,6 +2102,6 @@ VpSetRoundMode(unsigned long n)
- (… but not actually…)).
*/
-volatile double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
-volatile double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
+volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
+volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
static double
Zero(void)
@@ -2362,7 +2375,4 @@ VP_EXPORT U_LONG
VpInit(U_LONG BaseVal)
{
- U_LONG w;
- double v;
- /* Setup +/- Inf NaN -0 */
VpGetDoubleNaN();
@@ -2371,5 +2381,7 @@ VpInit(U_LONG BaseVal)
VpGetDoubleNegZero();
+#ifndef BASE_FIG
if(BaseVal <= 0) {
-
U_LONG w; /* Base <= 0, then determine Base by calcuration. */ BASE = 1;
@@ -2388,4 +2400,6 @@ VpInit(U_LONG BaseVal)
BASE_FIG = 0;
while(BaseVal /= 10) ++BASE_FIG;
+#endif
+
/* Allocates Vp constants. /
VpConstOne = VpAlloc((U_LONG)1, “1”);
@@ -2396,13 +2410,4 @@ VpInit(U_LONG BaseVal)
#endif / _DEBUG */
- /* Determine # of digits available in one ‘double’. */
- v = 1.0;
- DBLE_FIG = 0;
- while(v + 1.0 > 1.0) {
-
++DBLE_FIG;
-
v /= 10;
- }
#ifdef _DEBUG
if(gfDebug) {
@@ -2507,5 +2512,5 @@ VpAlloc(U_LONG mx, const char *szVal)
i = 0;
ipn = 0;
- while(psz[i]=szVal[ipn]) {
- while((psz[i]=szVal[ipn])!=0) {
if(ISDIGIT(psz[i])) ++ni;
if(psz[i]==’_’) {
@@ -2550,5 +2555,5 @@ VpAlloc(U_LONG mx, const char szVal)
/ Skip digits /
ni = 0; / digits in mantissa */
- while(v = szVal[i]) {
- while((v = szVal[i]) != 0) {
if(!ISDIGIT(v)) break;
++i;
@@ -2564,5 +2569,5 @@ VpAlloc(U_LONG mx, const char *szVal)
++i;
ipf = i;
-
while(v = szVal[i]) { /* get fraction part. */
-
while((v = szVal[i]) != 0) { /* get fraction part. */ if(!ISDIGIT(v)) break; ++i;
@@ -2582,5 +2587,5 @@ VpAlloc(U_LONG mx, const char *szVal)
v = szVal[i];
if((v == ‘-’) ||(v == ‘+’)) ++i;
-
while(v=szVal[i]) {
-
while((v=szVal[i])!=0) { if(!ISDIGIT(v)) break; ++i;
@@ -4440,5 +4445,5 @@ VpLeftRound(Real *y, int f, int nf)
v = y->frac[0];
nf -= VpExponent(y)*BASE_FIG;
- while(v=v/10) nf–;
- while((v /= 10) != 0) nf–;
nf += (BASE_FIG-1);
return VpMidRound(y,f,nf);
Index: ext/bigdecimal/extconf.rb
===================================================================
— ext/bigdecimal/extconf.rb (revision 15405)
+++ ext/bigdecimal/extconf.rb (working copy)
@@ -1,2 +1,12 @@
require ‘mkmf’
+base_fig = 0
+src = ("(BASE > 0) && "
-
"(BASE * (BASE+1)) > BASE && "
-
"(BASE * (BASE+1)) / BASE == (BASE+1)")
+while try_static_assert(src, nil, “-DBASE=10#{‘0’*base_fig}UL”)
- base_fig += 1
+end
+$defs << “-DBASE=1#{‘0’*base_fig}UL” << “-DBASE_FIG=#{base_fig}”
create_makefile(‘bigdecimal’)