github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/strconv/decimal.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  // Multiprecision decimal numbers.
     6  // For floating-point formatting only; not general purpose.
     7  // Only operations are assign and (binary) left/right shift.
     8  // Can do binary floating point in multiprecision decimal precisely
     9  // because 2 divides 10; cannot do decimal floating point
    10  // in multiprecision binary precisely.
    11  
    12  package strconv
    13  
    14  type decimal struct {
    15  	d     [800]byte // digits
    16  	nd    int       // number of digits used
    17  	dp    int       // decimal point
    18  	neg   bool
    19  	trunc bool // discarded nonzero digits beyond d[:nd]
    20  }
    21  
    22  func (a *decimal) String() string {
    23  	n := 10 + a.nd
    24  	if a.dp > 0 {
    25  		n += a.dp
    26  	}
    27  	if a.dp < 0 {
    28  		n += -a.dp
    29  	}
    30  
    31  	buf := make([]byte, n)
    32  	w := 0
    33  	switch {
    34  	case a.nd == 0:
    35  		return "0"
    36  
    37  	case a.dp <= 0:
    38  		// zeros fill space between decimal point and digits
    39  		buf[w] = '0'
    40  		w++
    41  		buf[w] = '.'
    42  		w++
    43  		w += digitZero(buf[w : w+-a.dp])
    44  		w += copy(buf[w:], a.d[0:a.nd])
    45  
    46  	case a.dp < a.nd:
    47  		// decimal point in middle of digits
    48  		w += copy(buf[w:], a.d[0:a.dp])
    49  		buf[w] = '.'
    50  		w++
    51  		w += copy(buf[w:], a.d[a.dp:a.nd])
    52  
    53  	default:
    54  		// zeros fill space between digits and decimal point
    55  		w += copy(buf[w:], a.d[0:a.nd])
    56  		w += digitZero(buf[w : w+a.dp-a.nd])
    57  	}
    58  	return string(buf[0:w])
    59  }
    60  
    61  func digitZero(dst []byte) int {
    62  	for i := range dst {
    63  		dst[i] = '0'
    64  	}
    65  	return len(dst)
    66  }
    67  
    68  // trim trailing zeros from number.
    69  // (They are meaningless; the decimal point is tracked
    70  // independent of the number of digits.)
    71  func trim(a *decimal) {
    72  	for a.nd > 0 && a.d[a.nd-1] == '0' {
    73  		a.nd--
    74  	}
    75  	if a.nd == 0 {
    76  		a.dp = 0
    77  	}
    78  }
    79  
    80  // Assign v to a.
    81  func (a *decimal) Assign(v uint64) {
    82  	var buf [24]byte
    83  
    84  	// Write reversed decimal in buf.
    85  	n := 0
    86  	for v > 0 {
    87  		v1 := v / 10
    88  		v -= 10 * v1
    89  		buf[n] = byte(v + '0')
    90  		n++
    91  		v = v1
    92  	}
    93  
    94  	// Reverse again to produce forward decimal in a.d.
    95  	a.nd = 0
    96  	for n--; n >= 0; n-- {
    97  		a.d[a.nd] = buf[n]
    98  		a.nd++
    99  	}
   100  	a.dp = a.nd
   101  	trim(a)
   102  }
   103  
   104  // Maximum shift that we can do in one pass without overflow.
   105  // Signed int has 31 bits, and we have to be able to accommodate 9<<k.
   106  const maxShift = 27
   107  
   108  // Binary shift right (* 2) by k bits.  k <= maxShift to avoid overflow.
   109  func rightShift(a *decimal, k uint) {
   110  	r := 0 // read pointer
   111  	w := 0 // write pointer
   112  
   113  	// Pick up enough leading digits to cover first shift.
   114  	n := 0
   115  	for ; n>>k == 0; r++ {
   116  		if r >= a.nd {
   117  			if n == 0 {
   118  				// a == 0; shouldn't get here, but handle anyway.
   119  				a.nd = 0
   120  				return
   121  			}
   122  			for n>>k == 0 {
   123  				n = n * 10
   124  				r++
   125  			}
   126  			break
   127  		}
   128  		c := int(a.d[r])
   129  		n = n*10 + c - '0'
   130  	}
   131  	a.dp -= r - 1
   132  
   133  	// Pick up a digit, put down a digit.
   134  	for ; r < a.nd; r++ {
   135  		c := int(a.d[r])
   136  		dig := n >> k
   137  		n -= dig << k
   138  		a.d[w] = byte(dig + '0')
   139  		w++
   140  		n = n*10 + c - '0'
   141  	}
   142  
   143  	// Put down extra digits.
   144  	for n > 0 {
   145  		dig := n >> k
   146  		n -= dig << k
   147  		if w < len(a.d) {
   148  			a.d[w] = byte(dig + '0')
   149  			w++
   150  		} else if dig > 0 {
   151  			a.trunc = true
   152  		}
   153  		n = n * 10
   154  	}
   155  
   156  	a.nd = w
   157  	trim(a)
   158  }
   159  
   160  // Cheat sheet for left shift: table indexed by shift count giving
   161  // number of new digits that will be introduced by that shift.
   162  //
   163  // For example, leftcheats[4] = {2, "625"}.  That means that
   164  // if we are shifting by 4 (multiplying by 16), it will add 2 digits
   165  // when the string prefix is "625" through "999", and one fewer digit
   166  // if the string prefix is "000" through "624".
   167  //
   168  // Credit for this trick goes to Ken.
   169  
   170  type leftCheat struct {
   171  	delta  int    // number of new digits
   172  	cutoff string //   minus one digit if original < a.
   173  }
   174  
   175  var leftcheats = []leftCheat{
   176  	// Leading digits of 1/2^i = 5^i.
   177  	// 5^23 is not an exact 64-bit floating point number,
   178  	// so have to use bc for the math.
   179  	/*
   180  		seq 27 | sed 's/^/5^/' | bc |
   181  		awk 'BEGIN{ print "\tleftCheat{ 0, \"\" }," }
   182  		{
   183  			log2 = log(2)/log(10)
   184  			printf("\tleftCheat{ %d, \"%s\" },\t// * %d\n",
   185  				int(log2*NR+1), $0, 2**NR)
   186  		}'
   187  	*/
   188  	{0, ""},
   189  	{1, "5"},                   // * 2
   190  	{1, "25"},                  // * 4
   191  	{1, "125"},                 // * 8
   192  	{2, "625"},                 // * 16
   193  	{2, "3125"},                // * 32
   194  	{2, "15625"},               // * 64
   195  	{3, "78125"},               // * 128
   196  	{3, "390625"},              // * 256
   197  	{3, "1953125"},             // * 512
   198  	{4, "9765625"},             // * 1024
   199  	{4, "48828125"},            // * 2048
   200  	{4, "244140625"},           // * 4096
   201  	{4, "1220703125"},          // * 8192
   202  	{5, "6103515625"},          // * 16384
   203  	{5, "30517578125"},         // * 32768
   204  	{5, "152587890625"},        // * 65536
   205  	{6, "762939453125"},        // * 131072
   206  	{6, "3814697265625"},       // * 262144
   207  	{6, "19073486328125"},      // * 524288
   208  	{7, "95367431640625"},      // * 1048576
   209  	{7, "476837158203125"},     // * 2097152
   210  	{7, "2384185791015625"},    // * 4194304
   211  	{7, "11920928955078125"},   // * 8388608
   212  	{8, "59604644775390625"},   // * 16777216
   213  	{8, "298023223876953125"},  // * 33554432
   214  	{8, "1490116119384765625"}, // * 67108864
   215  	{9, "7450580596923828125"}, // * 134217728
   216  }
   217  
   218  // Is the leading prefix of b lexicographically less than s?
   219  func prefixIsLessThan(b []byte, s string) bool {
   220  	for i := 0; i < len(s); i++ {
   221  		if i >= len(b) {
   222  			return true
   223  		}
   224  		if b[i] != s[i] {
   225  			return b[i] < s[i]
   226  		}
   227  	}
   228  	return false
   229  }
   230  
   231  // Binary shift left (/ 2) by k bits.  k <= maxShift to avoid overflow.
   232  func leftShift(a *decimal, k uint) {
   233  	delta := leftcheats[k].delta
   234  	if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
   235  		delta--
   236  	}
   237  
   238  	r := a.nd         // read index
   239  	w := a.nd + delta // write index
   240  	n := 0
   241  
   242  	// Pick up a digit, put down a digit.
   243  	for r--; r >= 0; r-- {
   244  		n += (int(a.d[r]) - '0') << k
   245  		quo := n / 10
   246  		rem := n - 10*quo
   247  		w--
   248  		if w < len(a.d) {
   249  			a.d[w] = byte(rem + '0')
   250  		} else if rem != 0 {
   251  			a.trunc = true
   252  		}
   253  		n = quo
   254  	}
   255  
   256  	// Put down extra digits.
   257  	for n > 0 {
   258  		quo := n / 10
   259  		rem := n - 10*quo
   260  		w--
   261  		if w < len(a.d) {
   262  			a.d[w] = byte(rem + '0')
   263  		} else if rem != 0 {
   264  			a.trunc = true
   265  		}
   266  		n = quo
   267  	}
   268  
   269  	a.nd += delta
   270  	if a.nd >= len(a.d) {
   271  		a.nd = len(a.d)
   272  	}
   273  	a.dp += delta
   274  	trim(a)
   275  }
   276  
   277  // Binary shift left (k > 0) or right (k < 0).
   278  func (a *decimal) Shift(k int) {
   279  	switch {
   280  	case a.nd == 0:
   281  		// nothing to do: a == 0
   282  	case k > 0:
   283  		for k > maxShift {
   284  			leftShift(a, maxShift)
   285  			k -= maxShift
   286  		}
   287  		leftShift(a, uint(k))
   288  	case k < 0:
   289  		for k < -maxShift {
   290  			rightShift(a, maxShift)
   291  			k += maxShift
   292  		}
   293  		rightShift(a, uint(-k))
   294  	}
   295  }
   296  
   297  // If we chop a at nd digits, should we round up?
   298  func shouldRoundUp(a *decimal, nd int) bool {
   299  	if nd < 0 || nd >= a.nd {
   300  		return false
   301  	}
   302  	if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
   303  		// if we truncated, a little higher than what's recorded - always round up
   304  		if a.trunc {
   305  			return true
   306  		}
   307  		return nd > 0 && (a.d[nd-1]-'0')%2 != 0
   308  	}
   309  	// not halfway - digit tells all
   310  	return a.d[nd] >= '5'
   311  }
   312  
   313  // Round a to nd digits (or fewer).
   314  // If nd is zero, it means we're rounding
   315  // just to the left of the digits, as in
   316  // 0.09 -> 0.1.
   317  func (a *decimal) Round(nd int) {
   318  	if nd < 0 || nd >= a.nd {
   319  		return
   320  	}
   321  	if shouldRoundUp(a, nd) {
   322  		a.RoundUp(nd)
   323  	} else {
   324  		a.RoundDown(nd)
   325  	}
   326  }
   327  
   328  // Round a down to nd digits (or fewer).
   329  func (a *decimal) RoundDown(nd int) {
   330  	if nd < 0 || nd >= a.nd {
   331  		return
   332  	}
   333  	a.nd = nd
   334  	trim(a)
   335  }
   336  
   337  // Round a up to nd digits (or fewer).
   338  func (a *decimal) RoundUp(nd int) {
   339  	if nd < 0 || nd >= a.nd {
   340  		return
   341  	}
   342  
   343  	// round up
   344  	for i := nd - 1; i >= 0; i-- {
   345  		c := a.d[i]
   346  		if c < '9' { // can stop after this digit
   347  			a.d[i]++
   348  			a.nd = i + 1
   349  			return
   350  		}
   351  	}
   352  
   353  	// Number is all 9s.
   354  	// Change to single 1 with adjusted decimal point.
   355  	a.d[0] = '1'
   356  	a.nd = 1
   357  	a.dp++
   358  }
   359  
   360  // Extract integer part, rounded appropriately.
   361  // No guarantees about overflow.
   362  func (a *decimal) RoundedInteger() uint64 {
   363  	if a.dp > 20 {
   364  		return 0xFFFFFFFFFFFFFFFF
   365  	}
   366  	var i int
   367  	n := uint64(0)
   368  	for i = 0; i < a.dp && i < a.nd; i++ {
   369  		n = n*10 + uint64(a.d[i]-'0')
   370  	}
   371  	for ; i < a.dp; i++ {
   372  		n *= 10
   373  	}
   374  	if shouldRoundUp(a, a.dp) {
   375  		n++
   376  	}
   377  	return n
   378  }