github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/strconv/atof.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package strconv 6 7 // decimal to binary floating point conversion. 8 // Algorithm: 9 // 1) Store input in multiprecision decimal. 10 // 2) Multiply/divide decimal by powers of two until in range [0.5, 1) 11 // 3) Multiply by 2^precision and round to get mantissa. 12 13 import "math" 14 15 var optimize = true // can change for testing 16 17 func equalIgnoreCase(s1, s2 string) bool { 18 if len(s1) != len(s2) { 19 return false 20 } 21 for i := 0; i < len(s1); i++ { 22 c1 := s1[i] 23 if 'A' <= c1 && c1 <= 'Z' { 24 c1 += 'a' - 'A' 25 } 26 c2 := s2[i] 27 if 'A' <= c2 && c2 <= 'Z' { 28 c2 += 'a' - 'A' 29 } 30 if c1 != c2 { 31 return false 32 } 33 } 34 return true 35 } 36 37 func special(s string) (f float64, ok bool) { 38 if len(s) == 0 { 39 return 40 } 41 switch s[0] { 42 default: 43 return 44 case '+': 45 if equalIgnoreCase(s, "+inf") || equalIgnoreCase(s, "+infinity") { 46 return math.Inf(1), true 47 } 48 case '-': 49 if equalIgnoreCase(s, "-inf") || equalIgnoreCase(s, "-infinity") { 50 return math.Inf(-1), true 51 } 52 case 'n', 'N': 53 if equalIgnoreCase(s, "nan") { 54 return math.NaN(), true 55 } 56 case 'i', 'I': 57 if equalIgnoreCase(s, "inf") || equalIgnoreCase(s, "infinity") { 58 return math.Inf(1), true 59 } 60 } 61 return 62 } 63 64 func (b *decimal) set(s string) (ok bool) { 65 i := 0 66 b.neg = false 67 b.trunc = false 68 69 // optional sign 70 if i >= len(s) { 71 return 72 } 73 switch { 74 case s[i] == '+': 75 i++ 76 case s[i] == '-': 77 b.neg = true 78 i++ 79 } 80 81 // digits 82 sawdot := false 83 sawdigits := false 84 for ; i < len(s); i++ { 85 switch { 86 case s[i] == '.': 87 if sawdot { 88 return 89 } 90 sawdot = true 91 b.dp = b.nd 92 continue 93 94 case '0' <= s[i] && s[i] <= '9': 95 sawdigits = true 96 if s[i] == '0' && b.nd == 0 { // ignore leading zeros 97 b.dp-- 98 continue 99 } 100 if b.nd < len(b.d) { 101 b.d[b.nd] = s[i] 102 b.nd++ 103 } else if s[i] != '0' { 104 b.trunc = true 105 } 106 continue 107 } 108 break 109 } 110 if !sawdigits { 111 return 112 } 113 if !sawdot { 114 b.dp = b.nd 115 } 116 117 // optional exponent moves decimal point. 118 // if we read a very large, very long number, 119 // just be sure to move the decimal point by 120 // a lot (say, 100000). it doesn't matter if it's 121 // not the exact number. 122 if i < len(s) && (s[i] == 'e' || s[i] == 'E') { 123 i++ 124 if i >= len(s) { 125 return 126 } 127 esign := 1 128 if s[i] == '+' { 129 i++ 130 } else if s[i] == '-' { 131 i++ 132 esign = -1 133 } 134 if i >= len(s) || s[i] < '0' || s[i] > '9' { 135 return 136 } 137 e := 0 138 for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { 139 if e < 10000 { 140 e = e*10 + int(s[i]) - '0' 141 } 142 } 143 b.dp += e * esign 144 } 145 146 if i != len(s) { 147 return 148 } 149 150 ok = true 151 return 152 } 153 154 // readFloat reads a decimal mantissa and exponent from a float 155 // string representation. It sets ok to false if the number could 156 // not fit return types or is invalid. 157 func readFloat(s string) (mantissa uint64, exp int, neg, trunc, ok bool) { 158 const uint64digits = 19 159 i := 0 160 161 // optional sign 162 if i >= len(s) { 163 return 164 } 165 switch { 166 case s[i] == '+': 167 i++ 168 case s[i] == '-': 169 neg = true 170 i++ 171 } 172 173 // digits 174 sawdot := false 175 sawdigits := false 176 nd := 0 177 ndMant := 0 178 dp := 0 179 for ; i < len(s); i++ { 180 switch c := s[i]; true { 181 case c == '.': 182 if sawdot { 183 return 184 } 185 sawdot = true 186 dp = nd 187 continue 188 189 case '0' <= c && c <= '9': 190 sawdigits = true 191 if c == '0' && nd == 0 { // ignore leading zeros 192 dp-- 193 continue 194 } 195 nd++ 196 if ndMant < uint64digits { 197 mantissa *= 10 198 mantissa += uint64(c - '0') 199 ndMant++ 200 } else if s[i] != '0' { 201 trunc = true 202 } 203 continue 204 } 205 break 206 } 207 if !sawdigits { 208 return 209 } 210 if !sawdot { 211 dp = nd 212 } 213 214 // optional exponent moves decimal point. 215 // if we read a very large, very long number, 216 // just be sure to move the decimal point by 217 // a lot (say, 100000). it doesn't matter if it's 218 // not the exact number. 219 if i < len(s) && (s[i] == 'e' || s[i] == 'E') { 220 i++ 221 if i >= len(s) { 222 return 223 } 224 esign := 1 225 if s[i] == '+' { 226 i++ 227 } else if s[i] == '-' { 228 i++ 229 esign = -1 230 } 231 if i >= len(s) || s[i] < '0' || s[i] > '9' { 232 return 233 } 234 e := 0 235 for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { 236 if e < 10000 { 237 e = e*10 + int(s[i]) - '0' 238 } 239 } 240 dp += e * esign 241 } 242 243 if i != len(s) { 244 return 245 } 246 247 if mantissa != 0 { 248 exp = dp - ndMant 249 } 250 ok = true 251 return 252 253 } 254 255 // decimal power of ten to binary power of two. 256 var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26} 257 258 func (d *decimal) floatBits(flt *floatInfo) (b uint64, overflow bool) { 259 var exp int 260 var mant uint64 261 262 // Zero is always a special case. 263 if d.nd == 0 { 264 mant = 0 265 exp = flt.bias 266 goto out 267 } 268 269 // Obvious overflow/underflow. 270 // These bounds are for 64-bit floats. 271 // Will have to change if we want to support 80-bit floats in the future. 272 if d.dp > 310 { 273 goto overflow 274 } 275 if d.dp < -330 { 276 // zero 277 mant = 0 278 exp = flt.bias 279 goto out 280 } 281 282 // Scale by powers of two until in range [0.5, 1.0) 283 exp = 0 284 for d.dp > 0 { 285 var n int 286 if d.dp >= len(powtab) { 287 n = 27 288 } else { 289 n = powtab[d.dp] 290 } 291 d.Shift(-n) 292 exp += n 293 } 294 for d.dp < 0 || d.dp == 0 && d.d[0] < '5' { 295 var n int 296 if -d.dp >= len(powtab) { 297 n = 27 298 } else { 299 n = powtab[-d.dp] 300 } 301 d.Shift(n) 302 exp -= n 303 } 304 305 // Our range is [0.5,1) but floating point range is [1,2). 306 exp-- 307 308 // Minimum representable exponent is flt.bias+1. 309 // If the exponent is smaller, move it up and 310 // adjust d accordingly. 311 if exp < flt.bias+1 { 312 n := flt.bias + 1 - exp 313 d.Shift(-n) 314 exp += n 315 } 316 317 if exp-flt.bias >= 1<<flt.expbits-1 { 318 goto overflow 319 } 320 321 // Extract 1+flt.mantbits bits. 322 d.Shift(int(1 + flt.mantbits)) 323 mant = d.RoundedInteger() 324 325 // Rounding might have added a bit; shift down. 326 if mant == 2<<flt.mantbits { 327 mant >>= 1 328 exp++ 329 if exp-flt.bias >= 1<<flt.expbits-1 { 330 goto overflow 331 } 332 } 333 334 // Denormalized? 335 if mant&(1<<flt.mantbits) == 0 { 336 exp = flt.bias 337 } 338 goto out 339 340 overflow: 341 // ±Inf 342 mant = 0 343 exp = 1<<flt.expbits - 1 + flt.bias 344 overflow = true 345 346 out: 347 // Assemble bits. 348 bits := mant & (uint64(1)<<flt.mantbits - 1) 349 bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits 350 if d.neg { 351 bits |= 1 << flt.mantbits << flt.expbits 352 } 353 return bits, overflow 354 } 355 356 // Exact powers of 10. 357 var float64pow10 = []float64{ 358 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 359 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 360 1e20, 1e21, 1e22, 361 } 362 var float32pow10 = []float32{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10} 363 364 // If possible to convert decimal representation to 64-bit float f exactly, 365 // entirely in floating-point math, do so, avoiding the expense of decimalToFloatBits. 366 // Three common cases: 367 // value is exact integer 368 // value is exact integer * exact power of ten 369 // value is exact integer / exact power of ten 370 // These all produce potentially inexact but correctly rounded answers. 371 func atof64exact(mantissa uint64, exp int, neg bool) (f float64, ok bool) { 372 if mantissa>>float64info.mantbits != 0 { 373 return 374 } 375 f = float64(mantissa) 376 if neg { 377 f = -f 378 } 379 switch { 380 case exp == 0: 381 // an integer. 382 return f, true 383 // Exact integers are <= 10^15. 384 // Exact powers of ten are <= 10^22. 385 case exp > 0 && exp <= 15+22: // int * 10^k 386 // If exponent is big but number of digits is not, 387 // can move a few zeros into the integer part. 388 if exp > 22 { 389 f *= float64pow10[exp-22] 390 exp = 22 391 } 392 if f > 1e15 || f < -1e15 { 393 // the exponent was really too large. 394 return 395 } 396 return f * float64pow10[exp], true 397 case exp < 0 && exp >= -22: // int / 10^k 398 return f / float64pow10[-exp], true 399 } 400 return 401 } 402 403 // If possible to compute mantissa*10^exp to 32-bit float f exactly, 404 // entirely in floating-point math, do so, avoiding the machinery above. 405 func atof32exact(mantissa uint64, exp int, neg bool) (f float32, ok bool) { 406 if mantissa>>float32info.mantbits != 0 { 407 return 408 } 409 f = float32(mantissa) 410 if neg { 411 f = -f 412 } 413 switch { 414 case exp == 0: 415 return f, true 416 // Exact integers are <= 10^7. 417 // Exact powers of ten are <= 10^10. 418 case exp > 0 && exp <= 7+10: // int * 10^k 419 // If exponent is big but number of digits is not, 420 // can move a few zeros into the integer part. 421 if exp > 10 { 422 f *= float32pow10[exp-10] 423 exp = 10 424 } 425 if f > 1e7 || f < -1e7 { 426 // the exponent was really too large. 427 return 428 } 429 return f * float32pow10[exp], true 430 case exp < 0 && exp >= -10: // int / 10^k 431 return f / float32pow10[-exp], true 432 } 433 return 434 } 435 436 const fnParseFloat = "ParseFloat" 437 438 func atof32(s string) (f float32, err error) { 439 if val, ok := special(s); ok { 440 return float32(val), nil 441 } 442 443 if optimize { 444 // Parse mantissa and exponent. 445 mantissa, exp, neg, trunc, ok := readFloat(s) 446 if ok { 447 // Try pure floating-point arithmetic conversion. 448 if !trunc { 449 if f, ok := atof32exact(mantissa, exp, neg); ok { 450 return f, nil 451 } 452 } 453 // Try another fast path. 454 ext := new(extFloat) 455 if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float32info); ok { 456 b, ovf := ext.floatBits(&float32info) 457 f = math.Float32frombits(uint32(b)) 458 if ovf { 459 err = rangeError(fnParseFloat, s) 460 } 461 return f, err 462 } 463 } 464 } 465 var d decimal 466 if !d.set(s) { 467 return 0, syntaxError(fnParseFloat, s) 468 } 469 b, ovf := d.floatBits(&float32info) 470 f = math.Float32frombits(uint32(b)) 471 if ovf { 472 err = rangeError(fnParseFloat, s) 473 } 474 return f, err 475 } 476 477 func atof64(s string) (f float64, err error) { 478 if val, ok := special(s); ok { 479 return val, nil 480 } 481 482 if optimize { 483 // Parse mantissa and exponent. 484 mantissa, exp, neg, trunc, ok := readFloat(s) 485 if ok { 486 // Try pure floating-point arithmetic conversion. 487 if !trunc { 488 if f, ok := atof64exact(mantissa, exp, neg); ok { 489 return f, nil 490 } 491 } 492 // Try another fast path. 493 ext := new(extFloat) 494 if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float64info); ok { 495 b, ovf := ext.floatBits(&float64info) 496 f = math.Float64frombits(b) 497 if ovf { 498 err = rangeError(fnParseFloat, s) 499 } 500 return f, err 501 } 502 } 503 } 504 var d decimal 505 if !d.set(s) { 506 return 0, syntaxError(fnParseFloat, s) 507 } 508 b, ovf := d.floatBits(&float64info) 509 f = math.Float64frombits(b) 510 if ovf { 511 err = rangeError(fnParseFloat, s) 512 } 513 return f, err 514 } 515 516 // ParseFloat converts the string s to a floating-point number 517 // with the precision specified by bitSize: 32 for float32, or 64 for float64. 518 // When bitSize=32, the result still has type float64, but it will be 519 // convertible to float32 without changing its value. 520 // 521 // If s is well-formed and near a valid floating point number, 522 // ParseFloat returns the nearest floating point number rounded 523 // using IEEE754 unbiased rounding. 524 // 525 // The errors that ParseFloat returns have concrete type *NumError 526 // and include err.Num = s. 527 // 528 // If s is not syntactically well-formed, ParseFloat returns err.Err = ErrSyntax. 529 // 530 // If s is syntactically well-formed but is more than 1/2 ULP 531 // away from the largest floating point number of the given size, 532 // ParseFloat returns f = ±Inf, err.Err = ErrRange. 533 func ParseFloat(s string, bitSize int) (float64, error) { 534 if bitSize == 32 { 535 f, err := atof32(s) 536 return float64(f), err 537 } 538 return atof64(s) 539 }