如何将从0到无穷大的值限制在0到1的范围内?

6
我有一个用Java编写的程序,它会生成一个浮点数aggressiveness,它的值可以从0到无穷大。我的目标是,当这个浮点数越高时,程序触发函数attackPawn()的概率就越高。
我已经找到了需要使用Math.random()函数的方法,该函数返回0到1之间的随机值。如果Math.random()小于0到1之间的float类型的aggressiveness值,我就调用函数attackPawn()
但是现在我遇到了困难,我无法将0到无穷大的aggressiveness转换成0到1之间的浮点数,其中1代表“无限” 的攻击性,0表示没有愤怒。
你有什么想法或者数学公式吗?

1
由于无穷大在现今的硬件上实际上是有限的,您可以通过Float.MAXVALUE来将“aggressiveness”进行除法运算。 - Dirk Lachowski
2
@DirkLachowski 这是一种非常有限的方法,因为在这个问题中存在双射,例如 tan(x*pi/2) - Absurd-Mind
如果您发布一些代码,无论您尝试了什么,都会非常有帮助。 - TechSpellBound
@Absurd-Mind 当然可以,但我不确定在游戏中是否需要数学上的正确性来衡量攻击性指标 - 对于游戏来说,速度比准确性更重要... - Dirk Lachowski
@DirkLachowski 您是正确的,不需要正确性。但是,如果问题是为了满足定义,则需要正确性。(然而最好更改定义) - Absurd-Mind
@Absurd-Mind 我同意,但问题中没有证据表明它必须是线性变换。但正如你建议的那样,改变攻击性的定义应该是正确的方法。 - Dirk Lachowski
5个回答

22

你希望有一个单调函数,将[0...正无穷]映射到[0..1]。 有许多选择:

    y=Math.atan(x)/(Math.PI/2);
    y=x/(1+x);
    y=1-Math.exp(-x);

还有更多的函数。每个函数都可以按比例扩展,只要给定正常数k>0

    y=Math.atan(k*x)/(Math.PI/2);
    y=x/(k+x);
    y=1-Math.exp(-k*x);

有无限多的选择,只需要选择一个适合你需求的。


2

可以将[0,正无穷)映射到[0,1),但这不会是线性的。一个示例函数如下:

y = tan(x * pi / 2);

这个函数的问题在于,你不能从中制作出正确的计算机程序,因为首先计算一个真正大的数字如10^5000并将其映射到[0,1)区间并不可能(或很困难)。但更好的解决方案是改变定义方式,例如:
0 = no aggression
1 = maximum aggression

使用这个方法,您无需映射数字。


1
尝试像这样做:

// aggressiveness is a float with a value between 0 and Float.MAX_VALUE or a value of Float.POSITIVE_INFINITY
if (aggressiveness == Float.POSITIVE_INFINITY) {
    aggressiveness = 1f;
} else {
    aggressiveness = aggressiveness / Float.MAX_VALUE;
}
// aggressiveness is now between 0 and 1 (inclusive)

0

虽然Double类支持无限值double d=Double.POSITIVE_INFINITY,但我认为您不能将其用于算术目的。最好定义一个最大值并将其视为无穷大。

double Min=0;
double Max= Double.MAX_VALUE;

double aggresiveness= Min + (Math.random() * ((Max - Min) + 1));

提示:如果您不想将其作为双精度数,也可以将aggressiveness视为longint


-1
尝试使用以下函数转换攻击性

public float function(float aggressiveness) {
    if(aggressiveness > 0F) {
        return 1 - (1 / aggressiveness);
    }
    return 0F;
}

这将把你的值映射到范围[0, 1)内;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接