什么时候(x == x + 2)?[关闭]


90

挑战:x以这样一种方式定义表达式,使表达式(x == x+2)求值为true。

我用C标记了问题,但欢迎使用其他语言的答案,只要它们具有创造力或突出语言的有趣方面即可。

我打算接受C解决方案,但其他语言也可以投票。

  1. 正确-适用于符合标准的实现。例外-假设是基本类型的实现,如果是常见实现(例如,假设int是32位2的补码),则可以。
  2. 简单-应该很小,使用基本语言功能。
  3. 有趣-我承认这是主观的。我有一些我认为有趣的示例,但我不想给出任何提示。更新:避免预处理器很有趣。
  4. 快速-第一个好的答案将被接受。

得到60个答案(我从没想到过这样的参与)后,总结一下可能会很好。

这60个答案分为7组,其中3组可以用C语言实现,其余用其他语言实现:

  1. C预处理程序。#define x 2|0有人建议,但还有许多其他可能性。
  2. 浮点。大数,无穷大或NaN都起作用。
  3. 指针算术。指向巨大结构的指针导致加2来回绕。

    其余的不适用于C:

  4. 运算符重载- +不加或==始终返回true的 A。
  5. 制作x一个函数调用(有些语言允许它没有x()语法)。然后,它每次都可以返回其他内容。
  6. 一位数据类型。然后x == x+2 (mod 2)
  7. 不断变化2-您0可以使用某种语言进行分配。

29
为什么4. Quick呢 您的意思是“谁认识一个人,并且有幸首先阅读此问题”?
卢克

6
@ugoren让社区投票(然后自己投票给自己喜欢的人),然后在7天左右后选择最佳答案:)
Luc

3
关于可能性2:NaN 不起作用。NaN + 2再次为NaN,但NaN == NaN为假。
马丁B

2
Scala解决方案(其中x是一个包含'2'的Set,而add to Set标准库中的+表示,而无需重新定义+自己)不属于IMHO这7类。
用户未知,

2
为什么这个问题和所有答案都在Community Wiki?
mbomb007

Answers:


71
main()
{
double x=1.0/0.0;
printf("%d",x==x+2);
}

输出1。

链接:http//ideone.com/dL6A5


7
float x=1./0有点短,也许更优雅。但是无论如何,这肯定是第一个好的答案。
ugoren

1
啊好老除以零。我花了更长的时间才弄明白我想承认的时间。哈哈
格兰特(Grant)

恩,我也有这个意思,但是在Windows上无法编译,所以我删除了它。:(尽管+1
Tudor

x = 1e999是执行此操作的另一种方法。
shiona 2012年

4
@shiona float x=1e20就足够了
l0n3sh4rk 2012年

125

Fortran IV:

2=0

此后,程序中的每个常数2均为零。相信我,我已经做到了(好,25年前)


23
更重要的是,我从未接触过Fortran。
C0deH4cker 2014年

3
它至少会发出警告吗?
2014年

15
@MichaelStern警告:您正在更改2的值!
Cruncher 2014年

100

这似乎可行:

#define x 2|0

基本上,将表达式扩展为(2|0 == 2|(0+2))。这是一个很好的例子,说明了为什么在定义宏时应该使用括号。


3
当然可以,并且我认为这是最优雅的基于预处理器的解决方案。但是我认为在没有前处理程序的情况下进行操作会更有趣。
ugoren

是我还是应该2|(0+2)1
phunehehe 2012年

1
@phunehehe:|逐位OR ; ||是逻辑或。
站在2012年

20
这使我想起了小鲍比桌子。
vsz 2012年

1
@rakeshNS:我添加了额外的括号集以显示运算符的优先级。这就是为什么我说“基本”。
PleaseStand

79

脑干

x

当然,这确实会使“评估为真”有些延误,因为在Brainfuck中,没有任何东西实际上可以评估任何东西–您只能操纵磁带。但是,如果现在添加表达式

x
(x == x+2)

该程序相当于

+

(因为所有内容<>+-[],.都是评论)。除了增加我们现在的值外,它什么都没有做。磁带用全零初始化,因此我们在光标位置最后得到1,表示“ true”:如果现在使用来开始条件段[],它将进入/循环。


12
+1必须是规则中最具创意的一环。
ninjalj 2012年

3
为什么需要x
詹姆斯,

3
@James问题说要定义,x因此这里x定义为x
2014年

1
@James的答案need除了+
Cruncher

56

F#

let (==) _ _ = true
let x = 0
x == (x + 2) //true

13
我喜欢这一个。不用
弄乱

4
等等,难道不是F#中的相等运算符=吗?==甚至没有默认定义。
Jwosty 2014年

50

C

int main() { float x = 1e10; printf("%d\n", x == x + 2); }

注意:如果不起作用FLT_EVAL_METHOD != 0(请参阅下面的评论)。


24
+1用于实际应用。太多的人不了解浮点数学。
Tim S.

1
@ mbomb007:我认为它们是不同的-您链接到的答案依赖INF + 2 == INF,而我的答案使用单个精度浮点数,该浮点数足够大,使得2小于一个ULP。
Paul R

2
@ mbomb007:我也认为它们是非常不同的- ∞ + 2 = ∞任何人都可以理解,并且不依赖于任何计算机特定的东西,而将2加到一个具体的数字上却没有任何作用,这有点令人惊讶,并且特定于有限的精度电脑和更有趣的恕我直言
GoatInTheMachine

1
FLT_EVAL_METHOD == 1数学完成时,这很容易失败double。推荐更大的FP值,以确保它甚至超过long double精度,例如1.0e37f
chux

1
@chux:感谢您的确认-绝对是我将来需要注意的事情,因为我的大部分代码最终都是跨平台的。
Paul R

36

C#

class T {
  static int _x;
  static int X { get { return _x -= 2; } }

  static void Main() { Console.WriteLine(X == X + 2); }
}

不是矮个子,而是有点优雅。

http://ideone.com/x56Ul


4
丢下它,此帖子刚刚获得了“很好的答案”徽章。说真的,要获得邪恶的徽章吗?不要在家做
fjdumont

这很邪恶,但它是如此美丽……
凯文

32

Scala: { val x = Set(2); (x == x + 2) }


Haskell:Booleans 上定义ℤ/ 2ℤ:

instance Num Bool where
    (+) = (/=)
    (-) = (+)
    (*) = (&&)
    negate = id
    abs    = id
    signum = id
    fromInteger = odd

那么x :: Bool我们就拥有了x == x + 2

更新:感谢您的意见,我相应地更新了实例。


3
您可以简化:fromInteger = odd
Rotsor 2012年

1
(+)可以定义为(/=)我相信的。
MatrixFrog 2012年

2
较短的解决方案是为创建一个实例()
Thomas Eding 2013年

31

蟒蛇

class X(int):__add__=lambda*y:0
x=X()

# Then (x == x+2) == True

真好 所有支持运算符重载的语言都可以使用类似的解决方案,但是C并不是其中一种。
ugoren

也有超载工作__cmp__class X(int):__cmp__=lambda*x:0(或__eq__虽然稍长class X(int):__eq__=lambda*x:True
博士jimbob

如果你不从int延长几个字符短..class X:__add__=lambda s,o:s
Doboy

我可以问一下乘法吗?
seequ 2014年

2
@TheRare实际上不是乘法。因为__add__通常给定多个参数(lambda x,y:),所以我使用*将所有参数打包到一个元组(lambda *y:)中来保存一些字符。有关更多信息,请参阅文档
grc 2014年

31

GNU C支持没有成员且大小为0的结构:

struct {} *x = 0;

2
非常好!我曾考虑过使用指针数据进行大量运算而导致回绕的算法,但并未想到相反的说法。
ugoren 2012年

26

PHP:

$x = true;
var_dump($x == $x+2);

要么:

var_dump(!($x==$x+2));

输出:

布尔值(true)


1
实际上,我实际上是想出这个简单的PHP答案,但是您击败了我。
2012年

25

常见的误解是,在C中,空格并不重要。我无法想象有人没有在GNU C中提出这个建议:

#include <stdio.h>
#define CAT_IMPL(c, d) (c ## d)
#define CAT(c, d) CAT_IMPL(c, d)
#define x CAT(a, __LINE__)

int main()
{
    int a9 = 2, a10 = 0;
    printf("%d\n", x ==
        x + 2);
    return 0;
}

印刷品1


很好,尽管在技术上可能无效(x == x+2仍然是错误的)。但是一旦提出这个主意,我认为#define x -2*__LINE__它会更优雅。
ugoren 2012年

3
@ugoren谢谢!如果你想这一切是在同一行,用计数器代替LINE -需要GCC 4.3+虽然。
H2CO3

1
_CAT是保留的标识符。凡是以下划线开始,大写字母被保留在C
康拉德·博罗夫斯基

完全正确的@xfix,已更新为删除UB。
H2CO3 2014年

20

C

在不使用宏且不滥用无限的情况下,它会更加有趣。

/////////////////////////////////////
// At the beginning                 /
// We assume truth!                 /

int truth = 1;
int x = 42;

/////////////////////////////////////
// Can the truth really be changed??/
truth = (x == x + 2);

/////////////////////////////////////
// The truth cannot be changed!     /
printf("%d",truth);

如果您不相信,请尝试一下!


1
0。不,仍然不相信。
MSalters 2012年

@MSalters:您使用什么编译器?您可能禁用了三边形。
vsz 2012年

VS2010。默认情况下,很可能禁用了三字母组合。要么行串联都不起作用??\
MSalters 2012年

MSalters:三部曲??\ 将被转换成一个图\ ,所以没有??\ 。但是,即使启用了某些现代编译器,默认情况下也会向三联字符和行串联警告。
vsz 2012年

18

Mathematica:

x /: x + 2 := x
x == x + 2

我认为该解决方案是新颖的,因为它使用了Mathematica的 Up Values概念。

编辑:

我正在扩展答案,以解释“增值”在Mathematica中的含义。

第一行实质上重新定义了符号的加法x。我可以将这样的定义直接存储在与+符号关联的全局函数中,但是这样的重新定义将很危险,因为重新定义可能会通过Mathematica的内置算法无法预测地传播。

取而代之的是,使用标签x/:,将定义与符号相关联x。现在,每当Mathematica看到该符号时x,它都会检查加法运算符是否正在+以某种形式的模式对其进行操作,x + 2 + ___其中该符号___表示其他符号可能为空序列。

此重新定义非常具体,并利用了Mathematica广泛的模式匹配功能。例如,表达式x+y+2返回x+y,但是表达式x+3返回x+3;因为在前一种情况下,可以匹配模式,但是在后一种情况下,如果没有其他简化,就不能匹配模式。


1
我认为您应该解释它的作用。大多数人不了解Mathematica(或什么是Up Values)。
ugoren 2012年

1
谢谢@ugoren,我大部分时间都花在Mathematica Stack Exchange网站上,所以我忘了解释什么使我的例子有意义。我进行了编辑,以尽可能简洁地解释该概念。
卡尔·莫里斯

17

Javascript:

var x = 99999999999999999;
alert(x == x+2);​

测试小提琴


2
您可以使用Infinity-Infinity,并且因此可以使用的快捷方式x = 1/0
zzzzBov 2012年

6
@zzzzBov:绝对是更好的代码高尔夫。我选择(99999999999999999 == 99999999999999999+2)它是因为我认为它比有趣得多(Infinity == Infinity+2),尽管正如OP所说的,“它是主观的” :)
Briguy37 2012年

这是唯一的现实情况,我有充分的理由(除了编程难题)看到了这样的检查:一种(基于浮点数的)教师功能正在检查其输入是否太大而无法递减-1并递归。语言本身就是Python,但是在这种情况下,这并不重要。
Alfe 2012年

5
@NicoBurns不正确:(
ajax333221 2012年

2
@NicoBurns,在控制台中运行该代码会产生false; 无论您从哪里获得有关JS的信息都是错误的,因此不应被信任。
zzzzBov 2012年



16

这是针对JavaScript的解决方案,它不利用浮点加法的Infinity-Infinity情况。这在Internet Explorer 8及更低版本中以及在选择加入的ES5严格模式下均不起作用。我不会将with声明和获取方法称为“高级”功能。

with ({ $: 0, get x() {return 2 * this.$--;} }) {
    console.log(x == x+2);
}

编辑补充:以上技巧,也可以不使用with,并get作为由著名安迪Ë提示在JavaScript高尔夫也由jncraton此页上:

var x = { $: 0, valueOf: function(){return 2 * x.$++;} };
console.log(x == x+2);

一个不错的概念- x尽管看起来像是变量读取,但使其成为函数调用。我假设从左到右的求值顺序,但这没关系,因为它是在JS中指定的(与C不同)。
ugoren 2012年

14

以下内容不是符合标准的C,但几乎可以在任何64位平台上运行:

int (*x)[0x2000000000000000];

原则上很好,但是似乎实现错误。x将以2 ^ 61的步长递增,因此x + 8等于x
ugoren 2012年

@ugoren,对我有效,在具有4字节的Linux上int
2012年

你是绝对正确的。我错过了一个事实int,不是char
ugoren 2012年

10

智者:

x=Mod(0,2)
x==x+2

返回True

通常对于GF(2 ** n),对于任何x,x = x + 2总是正确的

这不是错误或溢出或无穷大问题,实际上是正确的


1
PARI / GP使用同样的技巧
Hagen von Eitzen 2012年

10

普通口齿不清

* (defmacro x (&rest r) t)
X
* (x == x+2)
T

x不必一定是实际值时,这很容易。


8

APL(Dyalog)

X←1e15
X=X+2

APL甚至没有无穷大,它只是花车都不够精确地告诉之间的区别1.000.000.000.000.0001.000.000.000.000.002。据我所知,这是在APL中执行此操作的唯一方法。


我真的很喜欢,因为这是利用浮点精度的第一个答案。
AndrewKS 2012年

1
@AndrewKS:实际上,Paul R早一点。
MSalters 2012年

8

Perl 6

我很惊讶以前没有看到这个解决方案。总之,解决的办法是-如果有什么x02一次?my \x在这个例子中声明了无符号变量-这个问题问的x不是Perl风格的$x。该?? !!是三元运算符。

$ perl6 -e 'my \x = 0|2; say x == x + 2 ?? "YES" !! "NO"'
YES

但...

$ perl6 -e 'my \x = 0|2; say x == x + 3 ?? "YES" !! "NO"'
NO

x一次是多个值。x等于02立即。x + 2等于24立即。因此,从逻辑上讲,它们是平等的。


8

Python 2.X(使用(缓存的)整数重新定义)

我注意到所有的python答案都定义了重新定义+运算符的类。我将以更底层的python灵活性演示来回答。(这是特定于python2的代码段)

在python中,整数以这种方式或多或少地存储在C中:

typedef struct {            // NOTE: Macros have been expanded
    Py_ssize_t ob_refcnt;
    PyTypeObject *ob_type;
    long ob_ival;
} PyIntObject;

也就是说,有一个结构size_tvoid *以及long对象的顺序。
一旦使用并缓存了整数,就可以使用python的ctypes模块重新定义该整数,这样,不仅如此x == x+2,而且2 == 0

import ctypes
two = 2 # This will help us access the address of "2" so that we may change the value

# Recall that the object value is the third variable in the struct. Therefore,
# to change the value, we must offset the address we use by the "sizeof" a 
# size_t and a void pointer
offset = ctypes.sizeof(ctypes.c_size_t) + ctypes.sizeof(ctypes.c_voidp)

# Now we access the ob_ival by creating a C-int from the address of 
# our "two" variable, offset by our offset value.
# Note that id(variable) returns the address of the variable.
ob_ival = ctypes.c_int.from_address(id(two)+offset)

#Now we change the value at that address by changing the value of our int.
ob_ival.value = 0

# Now for the output
x = 1
print x == x+2
print 2 == 0

版画

True
True

7

佩尔

在包变量上使用具有副作用的子例程:

sub x () { $v -= 2 }
print "true!\n" if x == x + 2;

输出: true!


1
sub x{}“也有效” ..(至少在我的5.10.1中),但我不知道为什么..
mykhal 2012年

2
因为sub x{}返回undef或空列表,两者均为数字零。x + 2被解析为x(+2)。perl -MO=Deparse揭露print "true\n" if x() == x(2);
Perleone 2013年

太好了,@ mykhal和@Perleone!
memowe 2013年

7

蟒蛇

利用浮点精度使这一过程变得非常简单。

>>> x = 100000000000000000.0
>>> (x == x+2)
True

为了减少系统特定性,需要额外导入

>>> import sys
>>> x = float(sys.maxint + 1)
>>> (x == x+2)
True

这也应该适用于其他语言。之所以可行,是因为100000000000000000.0和100000000000000002.0的表示形式对于计算机完全相同,这是因为在计算机内部表示浮点的方式。有关更多信息,请参见http://en.wikipedia.org/wiki/IEEE_floating_point

因此,这基本上可以在允许您向浮点数添加整数并将其结果变为浮点数的任何语言中工作。


6

这是基于运算符重载的C ++解决方案。它依赖于从enum到的隐式转换int

#include <iostream>

enum X {};
bool operator==(X x, int y)
{
    return true;
}

int main()
{
    X x;
    std::cout << std::boolalpha << (x == x+2) << std::endl;
    return 0;
}

您可以使用std::boolalpha代替?:
乔恩·普迪

5

我知道这是一个代码挑战...但是我打了高尔夫。抱歉。

Ruby-13个字符-无限解决方案

x=1e17;x==x+2

返回true

Ruby-41个字符-Op重载解决方案

class Fixnum;def + y;0 end end;x=0;x==x+2

要么

class A;def self.+ y;A end end;x=A;x==x+2

5

如果可以利用这个问题,那么我将添加一些新的Java。这个技巧肯定不是新事物,但有趣的是,这在Java中是可能的。

static void pleaseDoNotDoThis() throws Exception {
    Field field = Boolean.class.getField("FALSE");
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, true);
}

public static void main(String args[]) throws Exception {
    pleaseDoNotDoThis();
    doit(1);
    doit("NO");
    doit(null);
    doit(Math.PI);
}

static void doit(long x) {
    System.out.format("(x == x + 2) = (%d == %d) = %s\n", x, x+2, (x == x + 2));
}

static void doit(String x) {
    System.out.format("(x == x + 2) = (%s == %s) = %s\n", x, x+2, (x == x + 2));
}

static void doit(double x) {
    System.out.format("(x == x + 2) = (%f == %f) = %s\n", x, x+2, (x == x + 2));
}

结果:

(x == x + 2) = (1 == 3) = true
(x == x + 2) = (NO == NO2) = true
(x == x + 2) = (null == null2) = true
(x == x + 2) = (3,141593 == 5,141593) = true
(x == x + 2) = (Infinity == Infinity) = true

4

此VBScript解决方案的工作方式与我的JavaScript解决方案相似。我没有使用预处理器,但解决方案似乎微不足道。

y = 0
Function x
x = y
y = -2
End Function

If x = x + 2 Then
    WScript.Echo "True"
Else
    WScript.Echo "False"
End If

我打算在ruby中发布相同的解决方案,直到看到您的解决方案为止-可能是因为两种语言都允许省略括号。
waldrumpus 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.