Merge pull request #1090 from andycheng123/fix/scale

fix/scale: fix LinearScale calculation
This commit is contained in:
Yo-An Lin 2023-03-10 14:18:02 +08:00 committed by GitHub
commit 78d65d74d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 18 deletions

View File

@ -134,33 +134,27 @@ type LinearScale struct {
Domain [2]float64 `json:"domain"` Domain [2]float64 `json:"domain"`
Range [2]float64 `json:"range"` Range [2]float64 `json:"range"`
a, b float64 // a is the ratio for Range to Domain
a float64
} }
func (s *LinearScale) Solve() error { func (s *LinearScale) Solve() error {
xs := s.Domain xs := s.Domain
ys := s.Range ys := s.Range
// y1 = a * x1 + b
// y2 = a * x2 + b
// y2 - y1 = (a * x2 + b) - (a * x1 + b)
// y2 - y1 = (a * x2) - (a * x1)
// y2 - y1 = a * (x2 - x1)
// a = (y2 - y1) / (x2 - x1)
// b = y1 - (a * x1)
s.a = (ys[1] - ys[0]) / (xs[1] - xs[0]) s.a = (ys[1] - ys[0]) / (xs[1] - xs[0])
s.b = ys[0] - (s.a * xs[0])
return nil return nil
} }
func (s *LinearScale) Call(x float64) (y float64) { func (s *LinearScale) Call(x float64) (y float64) {
if x < s.Domain[0] { if x <= s.Domain[0] {
x = s.Domain[0] return s.Range[0]
} else if x > s.Domain[1] { } else if x >= s.Domain[1] {
x = s.Domain[1] return s.Range[1]
} }
y = s.a*x + s.b y = s.Range[0] + (x-s.Domain[0])*s.a
return y return y
} }
@ -169,11 +163,11 @@ func (s *LinearScale) String() string {
} }
func (s *LinearScale) Formula() string { func (s *LinearScale) Formula() string {
return fmt.Sprintf("f(x) = %f * x + %f", s.a, s.b) return fmt.Sprintf("f(x) = %f + (x - %f) * %f", s.Range[0], s.Domain[0], s.a)
} }
func (s *LinearScale) FormulaOf(x float64) string { func (s *LinearScale) FormulaOf(x float64) string {
return fmt.Sprintf("f(%f) = %f * %f + %f", x, s.a, x, s.b) return fmt.Sprintf("f(%f) = %f + (%f - %f) * %f", x, s.Range[0], x, s.Domain[0], s.a)
} }
// see also: http://www.vb-helper.com/howto_find_quadratic_curve.html // see also: http://www.vb-helper.com/howto_find_quadratic_curve.html

View File

@ -73,8 +73,9 @@ func TestLinearScale(t *testing.T) {
err := scale.Solve() err := scale.Solve()
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "f(x) = 0.007000 * x + -4.000000", scale.String()) assert.Equal(t, "f(x) = 3.000000 + (x - 1000.000000) * 0.007000", scale.String())
assert.InDelta(t, 3, scale.Call(1000), delta) assert.InDelta(t, 3, scale.Call(1000), delta)
assert.InDelta(t, 6.5, scale.Call(1500), delta)
assert.InDelta(t, 10, scale.Call(2000), delta) assert.InDelta(t, 10, scale.Call(2000), delta)
for x := 1000; x <= 2000; x += 100 { for x := 1000; x <= 2000; x += 100 {
y := scale.Call(float64(x)) y := scale.Call(float64(x))
@ -90,8 +91,23 @@ func TestLinearScale2(t *testing.T) {
err := scale.Solve() err := scale.Solve()
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "f(x) = 0.150000 * x + -0.050000", scale.String()) assert.Equal(t, "f(x) = 0.100000 + (x - 1.000000) * 0.150000", scale.String())
assert.InDelta(t, 0.1, scale.Call(1), delta) assert.InDelta(t, 0.1, scale.Call(1), delta)
assert.InDelta(t, 0.25, scale.Call(2), delta)
assert.InDelta(t, 0.4, scale.Call(3), delta)
}
func TestLinearScaleNegative(t *testing.T) {
scale := LinearScale{
Domain: [2]float64{-1, 3},
Range: [2]float64{0.1, 0.4},
}
err := scale.Solve()
assert.NoError(t, err)
assert.Equal(t, "f(x) = 0.100000 + (x - -1.000000) * 0.075000", scale.String())
assert.InDelta(t, 0.1, scale.Call(-1), delta)
assert.InDelta(t, 0.25, scale.Call(1), delta)
assert.InDelta(t, 0.4, scale.Call(3), delta) assert.InDelta(t, 0.4, scale.Call(3), delta)
} }