...

Source file src/strconv/fp_test.go

Documentation: strconv

		 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_test
		 6  
		 7  import (
		 8  	"bufio"
		 9  	"fmt"
		10  	"os"
		11  	"strconv"
		12  	"strings"
		13  	"testing"
		14  )
		15  
		16  func pow2(i int) float64 {
		17  	switch {
		18  	case i < 0:
		19  		return 1 / pow2(-i)
		20  	case i == 0:
		21  		return 1
		22  	case i == 1:
		23  		return 2
		24  	}
		25  	return pow2(i/2) * pow2(i-i/2)
		26  }
		27  
		28  // Wrapper around strconv.ParseFloat(x, 64).	Handles dddddp+ddd (binary exponent)
		29  // itself, passes the rest on to strconv.ParseFloat.
		30  func myatof64(s string) (f float64, ok bool) {
		31  	a := strings.SplitN(s, "p", 2)
		32  	if len(a) == 2 {
		33  		n, err := strconv.ParseInt(a[0], 10, 64)
		34  		if err != nil {
		35  			return 0, false
		36  		}
		37  		e, err1 := strconv.Atoi(a[1])
		38  		if err1 != nil {
		39  			println("bad e", a[1])
		40  			return 0, false
		41  		}
		42  		v := float64(n)
		43  		// We expect that v*pow2(e) fits in a float64,
		44  		// but pow2(e) by itself may not. Be careful.
		45  		if e <= -1000 {
		46  			v *= pow2(-1000)
		47  			e += 1000
		48  			for e < 0 {
		49  				v /= 2
		50  				e++
		51  			}
		52  			return v, true
		53  		}
		54  		if e >= 1000 {
		55  			v *= pow2(1000)
		56  			e -= 1000
		57  			for e > 0 {
		58  				v *= 2
		59  				e--
		60  			}
		61  			return v, true
		62  		}
		63  		return v * pow2(e), true
		64  	}
		65  	f1, err := strconv.ParseFloat(s, 64)
		66  	if err != nil {
		67  		return 0, false
		68  	}
		69  	return f1, true
		70  }
		71  
		72  // Wrapper around strconv.ParseFloat(x, 32).	Handles dddddp+ddd (binary exponent)
		73  // itself, passes the rest on to strconv.ParseFloat.
		74  func myatof32(s string) (f float32, ok bool) {
		75  	a := strings.SplitN(s, "p", 2)
		76  	if len(a) == 2 {
		77  		n, err := strconv.Atoi(a[0])
		78  		if err != nil {
		79  			println("bad n", a[0])
		80  			return 0, false
		81  		}
		82  		e, err1 := strconv.Atoi(a[1])
		83  		if err1 != nil {
		84  			println("bad p", a[1])
		85  			return 0, false
		86  		}
		87  		return float32(float64(n) * pow2(e)), true
		88  	}
		89  	f64, err1 := strconv.ParseFloat(s, 32)
		90  	f1 := float32(f64)
		91  	if err1 != nil {
		92  		return 0, false
		93  	}
		94  	return f1, true
		95  }
		96  
		97  func TestFp(t *testing.T) {
		98  	f, err := os.Open("testdata/testfp.txt")
		99  	if err != nil {
	 100  		t.Fatal("testfp: open testdata/testfp.txt:", err)
	 101  	}
	 102  	defer f.Close()
	 103  
	 104  	s := bufio.NewScanner(f)
	 105  
	 106  	for lineno := 1; s.Scan(); lineno++ {
	 107  		line := s.Text()
	 108  		if len(line) == 0 || line[0] == '#' {
	 109  			continue
	 110  		}
	 111  		a := strings.Split(line, " ")
	 112  		if len(a) != 4 {
	 113  			t.Error("testdata/testfp.txt:", lineno, ": wrong field count")
	 114  			continue
	 115  		}
	 116  		var s string
	 117  		var v float64
	 118  		switch a[0] {
	 119  		case "float64":
	 120  			var ok bool
	 121  			v, ok = myatof64(a[2])
	 122  			if !ok {
	 123  				t.Error("testdata/testfp.txt:", lineno, ": cannot atof64 ", a[2])
	 124  				continue
	 125  			}
	 126  			s = fmt.Sprintf(a[1], v)
	 127  		case "float32":
	 128  			v1, ok := myatof32(a[2])
	 129  			if !ok {
	 130  				t.Error("testdata/testfp.txt:", lineno, ": cannot atof32 ", a[2])
	 131  				continue
	 132  			}
	 133  			s = fmt.Sprintf(a[1], v1)
	 134  			v = float64(v1)
	 135  		}
	 136  		if s != a[3] {
	 137  			t.Error("testdata/testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",
	 138  				"want ", a[3], " got ", s)
	 139  		}
	 140  	}
	 141  	if s.Err() != nil {
	 142  		t.Fatal("testfp: read testdata/testfp.txt: ", s.Err())
	 143  	}
	 144  }
	 145  

View as plain text