예제 #1
0
func TestRound(t *testing.T) {

	tests := []struct {
		val, roundOn float64
		places       int
		want         float64
	}{
		{1234.56, .5, 1, 1234.6},
		{123.445, .5, 2, 123.45},
	}

	for _, test := range tests {
		have := util.Round(test.val, test.roundOn, test.places)
		assert.EqualValues(t, test.want, have, "%v", test)
	}
}
예제 #2
0
파일: money.go 프로젝트: joao-parana/csfw
// Swedish applies the Swedish rounding. You may set the usual options.
// TODO: Consider text/currency package based on Valuta field
func (m Money) Swedish(opts ...Option) Money {
	m.Option(opts...)
	const (
		roundOn float64 = .5
		places  int     = 0
	)
	switch m.Interval {
	case Interval005:
		// NL, SG, SA, CH, TR, CL, IE
		// 5 cent rounding
		return m.Setf(util.Round(m.Getf()*20, roundOn, places) / 20) // base 5
	case Interval010:
		// New Zealand & Hong Kong
		// 10 cent rounding
		// In Sweden between 1985 and 1992, prices were rounded up for sales
		// ending in 5 öre.
		return m.Setf(util.Round(m.Getf()*10, roundOn, places) / 10)
	case Interval015:
		// 10 cent rounding, special case
		// Special case: In NZ, it is up to the business to decide if they
		// will round 5¢ intervals up or down. The majority of retailers follow
		// government advice and round it down.
		if m.m%5 == 0 {
			m.m = m.m - 1
		}
		return m.Setf(util.Round(m.Getf()*10, roundOn, places) / 10)
	case Interval025:
		// round to quarter
		return m.Setf(util.Round(m.Getf()*4, roundOn, places) / 4)
	case Interval050:
		// 50 cent rounding
		// The system used in Sweden from 1992 to 2010, in Norway from 1993 to 2012,
		// and in Denmark since 1 October 2008 is the following:
		// Sales ending in 1–24 öre round down to 0 öre.
		// Sales ending in 25–49 öre round up to 50 öre.
		// Sales ending in 51–74 öre round down to 50 öre.
		// Sales ending in 75–99 öre round up to the next whole Krone/krona.
		return m.Setf(util.Round(m.Getf()*2, roundOn, places) / 2)
	case Interval100:
		// The system used in Sweden since 30 September 2010 and used in Norway since 1 May 2012.
		// Sales ending in 1–49 öre/øre round down to 0 öre/øre.
		// Sales ending in 50–99 öre/øre round up to the next whole krona/krone.
		return m.Setf(util.Round(m.Getf()*1, roundOn, places) / 1) // ;-)
	}
	return m
}
예제 #3
0
파일: number.go 프로젝트: joao-parana/csfw
// FmtFloat64 formats a float value, does internal maybe incorrect rounding.
// Thread safe
func (no *Number) FmtFloat64(w io.Writer, f float64) (int, error) {
	sign := 1
	if f < 0 {
		sign = -sign
	}

	// Special cases:
	//   NaN = "NaN"
	//   +Inf = "+Infinity"
	//   -Inf = "-Infinity"

	if math.IsNaN(f) {
		return w.Write(no.sym.Nan)
	}

	if f > floatMax64 {
		no.mu.Lock()
		defer no.mu.Unlock()
		no.clearBuf()

		wr := utf8.EncodeRune(no.buf, no.sym.Infinity)
		return w.Write(no.buf[:wr])
	}
	if f < -floatMax64 {
		no.mu.Lock()
		defer no.mu.Unlock()
		no.clearBuf()

		wr := utf8.EncodeRune(no.buf, no.sym.MinusSign)
		wr += utf8.EncodeRune(no.buf[wr:], no.sym.Infinity)
		no.buf = no.buf[:numberBufferSize]
		return w.Write(no.buf[:wr])
	}

	if isInt(f) { // check if float is integer value
		return no.FmtInt64(w, int64(f))
	}

	usedFmt, err := no.GetFormat(sign < 0)
	if err != nil {
		if PkgLog.IsDebug() {
			PkgLog.Debug("i18n.Number.FmtFloat64.GetFormat", "err", err, "format", usedFmt.String())
		}
		return 0, errgo.Mask(err)
	}

	// to test the next lines: http://play.golang.org/p/L0ykFv3G4B
	precPow10 := math.Pow10(usedFmt.precision)

	var modf float64
	if f > 0 {
		modf = f + (5 / (precPow10 * 10))
	} else {
		modf = f - (5 / (precPow10 * 10))
	}
	intgr, fracf := math.Modf(modf)

	if fracf < 0 {
		fracf = -fracf
	}

	fracI := int64(util.Round(fracf*precPow10, 0, usedFmt.precision))

	return no.FmtNumber(w, sign, int64(intgr), intLen(fracI), fracI)
}
예제 #4
0
파일: money.go 프로젝트: joao-parana/csfw
// Mul multiplies two Currency types. Both types must have the same precision.
func (m Money) Mul(d Money) Money {
	// @todo c.m*d.m will overflow int64
	r := util.Round(float64(m.m*d.m)/m.dpf, .5, 0)
	return m.Set(int64(r))
}