使用对数缩放计算线的子分段

时间:2017-11-16 18:22:41

标签: javascript math logarithm

我想计算长度为totalLineLength的行的子段的长度,其中子段与给定事件的对数成比例。

直观表示:| --- | ----- | --------- |由子分段组成的一行。

我希望计算出的子分段的总和等于totalLineLength,并且必须打印Success。也必须使用Log(x+1)(因为它总是为正面参数提供积极结果,并且也会给出1。)

使用线性缩放,我这样做,并且它可以工作。

var totalLineLength = 20;
var eventTotal;
var calcSubSegment = function(x) {
    return totalLineLength * x / eventTotal;
}

var events = [0.1, 1, 22];
eventTotal = events.reduce((a, b) => a + b, 0);
var subSegments = events.map(calcSubSegment);
var segmentLength = subSegments.reduce((a, b) => a + b);
if (segmentLength != totalLineLength) {
    console.log("Error:", segmentLength);
} else {
    console.log("Success");
}

使用log(x + 1)(更新calcSubSegment),它不起作用。

var totalLineLength = 20;
var eventTotal;
var calcSubSegment = function(x) {
    return totalLineLength * Math.log(x+1) / Math.log(eventTotal+1);
}

var events = [0.1, 1, 22];
eventTotal = events.reduce((a, b) => a + b, 0);
var subSegments = events.map(calcSubSegment);
var segmentLength = subSegments.reduce((a, b) => a + b, 0);
if (segmentLength != totalLineLength) {
    console.log("Error:", segmentLength);
} else {
    console.log("Success");
}

我的代码出了什么问题?我想eventTotal计算,但我不知道如何继续。

我应该如何使用对数缩放?我也想要一个数学解释。

1 个答案:

答案 0 :(得分:2)

如果我正确理解您的任务,最简单的解决方案是map所有events使用您的log(x+1)函数,然后使用您已实施的线性拆分。像这样:

function linearSplit(events, totalLineLength) {
	var eventTotal;
	var calcSubSegment = function(x) {
		return totalLineLength * x / eventTotal;
	}

	eventTotal = events.reduce((a, b) => a + b, 0);
	var subSegments = events.map(calcSubSegment);
	return subSegments;
}


function logSplit(events, totalLineLength) {
	var logEvents = events.map(function(x) { return Math.log(x+1); } );
	return linearSplit(logEvents, totalLineLength);
}



function testSplit(events, totalLineLength, fnSplit, splitName) {
	var subSegments = fnSplit(events, totalLineLength);
	var segmentLength = subSegments.reduce((a, b) => a + b, 0);
	console.log(splitName + ":\n"  + events + " =>\n" + subSegments);
	if (Math.abs(segmentLength - totalLineLength) > 0.001) {
		console.log(splitName + " Error:", segmentLength);
	} else {
		console.log(splitName + " Success");
	}
}

var totalLineLength = 20;
var events = [0.1, 1, 22];

testSplit(events, totalLineLength, linearSplit, "linearSplit");
testSplit(events, totalLineLength, logSplit, "logSplit"); 

这个想法是唯一的分裂

  1. 具有与某些系数成比例的部分
  2. 使所有部分的总和等于整个
  3. 同时是线性分裂。因此,如果要以任何方式缩放系数,则应在传递给线性分割逻辑之前对其进行缩放。否则,部件的总和将不会与代码中的整体(在任何非线性缩放的情况下)相等。

    P.S。将浮点值与==进行比较并不是一个好主意。您应该对计算/舍入误差使用一些容差。