【问题标题】:if x>=1, then 1, otherwise 0, as pure math equation?如果 x>=1,则为 1,否则为 0,作为纯数学方程?
【发布时间】:2021-06-05 12:37:00
【问题描述】:

由于某些开发工具的限制,我正在寻找以下数学表达式:

If x>=1:
    y = 1
else:
    y = 0

如果增加简单性,X必须是大于或等于0的整数。

绝对允许的操作: +、-、/、*、**(幂)

不允许的操作: 不允许使用绝对值。 不允许使用 >、=、!=、==。 使用“如果”

例如不允许: y = 1*(x>=1)

(由于使用了>=)

对于附加信息,我正在尝试向 google 的 or-tools 添加一些约束, 如果 X>=0 则 y+=1...

编辑:我在 python 中工作。

【问题讨论】:

  • 您正在寻找sign function
  • y = 1 - 0**x? (当然,这取决于您的工具认为 0**0 是什么。)
  • @user1639926 是否允许使用逻辑运算符:AND、OR、XOR、NOT?
  • @user1639926 知道整数包含多少位吗?
  • 0/0 在你的语言中是做什么的?我在想y = x / x 可能有用。

标签: python math


【解决方案1】:

我想说的是,没有办法使用有限数量的仅具有组合和连续运算符的连续函数来定义像y(x) 这样的中断函数。

你可以得到类似abs(x)(x ** 2) ** 0.5 的东西,但我不明白你如何使用它(它有一个不连续的一阶导数,但它仍然是连续的)来获得一个完美的阶跃函数,在任何地方都定义了指定的值在步骤点。

0.5 + 0.5 * abs(x-1)/(x-1) 之类的东西几乎是您在任何地方都在寻找的东西,但是您将遇到奇点 x=1 的问题,其中 0/0 将被评估。

编辑

如果输入 x 保证为整数,则解决方案很简单:

def y(x):
    return 0.5 + 0.5 * abs(x - 0.5) / (x - 0.5)

或者,使用电源定义abs...

def y(x):
    return 0.5 + 0.5 * ((x - 0.5) ** 2) ** 0.5 / (x - 0.5)

x=0.5 的函数未定义,但如果仅对整数求值,则没有问题。

另一种选择是

def y(x):
    return 0.5 + abs(x - 0.25) + (x - 0.25) - abs(abs(x-0.25) + (x-0.25) - 0.5)

这是一个连续函数,在 0.25 之前为 0,随着 x 从 0.25 变为 0.75,从 0 线性变为 1,之后保持为 1。

【讨论】:

  • 很可能有一个连续函数在整数上取所需的值,因为对于非整数取什么值没有要求。
  • @kaya3:在那种情况下,解决方案很简单......见编辑
  • @kaya3:重新阅读问题更简单,因为 x 不仅是整数,而且 >=0。所以寻找的是一个 0 代表 0 和 1 代表其他任何东西的函数......
【解决方案2】:

在这种情况下,我建议如下: 由于 x 是整数且x>=0,因此以下逻辑为真:

如果x > 00**x == 0 否则0**x == 1。这等于 如果x >=1 然后0**x == 0 否则0**x == 1

所以y = 1 - 0**x 会给出想要的结果。

【讨论】:

  • 嗯,这在很大程度上取决于在相应工具中如何评估 0**0。支持和反对0**0 == 10**0 == 0 都有很好的论据
  • @derpirscher 如果我们谈论数学,数学上 0**0 等于 1。您可以使用计算器检查它。请特别注意,Q 仅标记为 math,没有提及具体的工具。
  • 不,特别是如果我们谈论“数学”没有明确的答案,0**0 的结果是什么。仅仅因为一些随机计算器返回某个数字,并不意味着它是正确的......你是对的,大多数系统将返回1,并且某些数学领域使用1,但其他人倾向于假设它的值未定义en.wikipedia.org/wiki/Zero_to_the_power_of_zero
  • @derpirscher 你是对的。我能提出的唯一论点是我们正在谈论的函数不是连续的。它只需要整数值。再次感谢您的评论。
  • 这与连续与否无关。一方面x**0 == 1 代表所有x,另一方面0**x == 0 代表所有x。所以如果你在这两种情况下都输入x = 0,你会得到一个矛盾。我自己不是数学家,但根据你在大学问的人,你得到不同的答案,即 0、1、未定义或“取决于...”
【解决方案3】:

让我们看看这里,你基本上有一个不等式x-1>=0

y = (x-1)/abs(x-1) 将为您提供您正在寻找的所有情况下的值,x=0 除外。在这种情况下会抛出一个异常,也许你可以用它来设置 y 的值。 就像这样:

try{
y=(x-1)/abs(x-1);
} catch(ArithmaticException e){
y = 1}

【讨论】:

  • OP 指出不允许使用abs。但在我看来这并非不合理......为什么不直接使用 y = x/x 并捕获错误让 y = 0? OP 还指出 x 将是一个非负整数。
【解决方案4】:

由于已知整数是非负数,因此可以简单地将整数的所有位一一地或在一起。结果是所需的谓词。在源操作数用完之前执行按位 OR-ing 的简单循环需要比较,这是不允许的。

在我现在可以看到的强加限制下,唯一可行的替代方法是使用直线代码,该代码重复位提取过程的步骤与整数的位数一样多。这是我在下面的 ISO-C99 代码中使用的。每个位都是用 DIV 和 MOD 提取的。两个一位变量 st 的 OR 计算为 s + t - s * t。对 32 位整数进行简单的详尽测试,证实这种方法是可行的,但效率显然不是很高。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define OR1(s,t)  (s + t - s * t)

// (x >= 1) ? 1 : 0
uint32_t ge1 (uint32_t x)
{
    uint32_t y;

    y = OR1 (
             OR1 (
                 OR1 (OR1 (OR1 ((x / 0x00000001) % 2, (x / 0x00000002) % 2),
                           OR1 ((x / 0x00000004) % 2, (x / 0x00000008) % 2)),
                      OR1 (OR1 ((x / 0x00000010) % 2, (x / 0x00000020) % 2),
                           OR1 ((x / 0x00000040) % 2, (x / 0x00000080) % 2))),
                 OR1 (OR1 (OR1 ((x / 0x00000100) % 2, (x / 0x00000200) % 2),
                           OR1 ((x / 0x00000400) % 2, (x / 0x00000800) % 2)),
                      OR1 (OR1 ((x / 0x00001000) % 2, (x / 0x00002000) % 2),
                           OR1 ((x / 0x00004000) % 2, (x / 0x00008000) % 2)))), 
             OR1 (
                 OR1 (OR1 (OR1 ((x / 0x00010000) % 2, (x / 0x00020000) % 2),
                           OR1 ((x / 0x00040000) % 2, (x / 0x00080000) % 2)),
                      OR1 (OR1 ((x / 0x00100000) % 2, (x / 0x00200000) % 2),
                           OR1 ((x / 0x00400000) % 2, (x / 0x00800000) % 2))),
                 OR1 (OR1 (OR1 ((x / 0x01000000) % 2, (x / 0x02000000) % 2),
                           OR1 ((x / 0x04000000) % 2, (x / 0x08000000) % 2)),
                      OR1 (OR1 ((x / 0x10000000) % 2, (x / 0x20000000) % 2),
                           OR1 ((x / 0x40000000) % 2, (x / 0x80000000) % 2)))));
    return y;
}

int main (void)
{
    uint32_t x, res, ref;

    x = 0;
    do {
        res = ge1 (x);
        ref = x >= 1;
        if (res != ref) {
            printf ("error: x=%08x  res=%08x  ref=%08x\n", x, res, ref);
            return EXIT_FAILURE;
        }
        x++;
    } while (x);
    printf ("test passed\n");
    return EXIT_SUCCESS;
}

【讨论】:

    【解决方案5】:

    对于整数x,如果abs可以,那么我建议

    y = (x + abs(x)) / (abs(x+1) + abs(x-1))
    

    这不会被零除,并且对于每个整数x,无论正数还是负数,除法都是精确的,只要不发生溢出,因此可以用整数算术计算。

    如果你不关心负 x,那就更简单了:

    y = (abs(x+1) - abs(x-1)) / 2
    

    如果函数需要对整个有界整数域进行操作,则应使用一些更大的 int 算法,或者您可以在浮点算法中使用相同的函数与 float(x),或者同样可以回退到答案@6502 在这种情况下更简单。

    编辑如果你没有绝对值,你可以试试1-(2.0**(-x))**n,n 足够大,以便利用浮点下溢和/或有限的精度。 n=2000 应该足以导致每个正整数输入的下溢,但没有用那么高的 n,因为 n=100 应该足以导致在大多数架构上不精确地舍入为 1。即使使用浮点运算,高效评估也非常简单,您可以使用单个幂 1.0-(2.0**(-100.0*x))。对于负整数输入,将 x 替换为 x*x。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-09
      • 2016-12-01
      相关资源
      最近更新 更多