这是一种非常基本的操作,我经常写,所以我想探索最短、最清晰的方法来完成它。以下是我目前为止最好的方法:
v = (v == 0 ? 1 : 0);
你能改进这个吗?
编辑:问题是问如何以最少的字符数写出上述语句,同时保持清晰度 - 这怎么会是“不是一个真正的问题”?虽然有些有趣的答案来自人们把它当作高尔夫练习,但这并不是旨在成为一项代码高尔夫练习,很高兴看到高尔夫被用于积极和发人深省的方式。
v = (v == 0 ? 1 : 0);
你可以简单地使用:
v = 1 - v;
当然,这假定变量已经被正确初始化了,也就是说它只有值0或1。
另一种更短的方法,但使用的运算符较不常见:
v ^= 1;
为了明确,我从未将这个问题视为代码高尔夫,只是想找到一种在不使用任何模糊技巧(如操作符的副作用)的情况下完成任务的简短方法。
v ^= 1
不清晰,就要让他停止编程,这种说法有些严厉。正如先前所述,它不是最常见的运算符之一,也与v = v ^ 1
的作用不同。此外,该运算符在不同的语言(如VB)中意义完全不同。是的,快速查询将告诉您它是一个异或运算符,并且您将理解它的作用,但对许多人来说,一眼并不明显。我认为这并不意味着你需要辞职。 - JD Isaacks因为0
是false
值,而1
是true
值。
v = (v ? 0 : 1);
如果你愿意使用 true
和 false
而不是数字,那就可以这样做。v = !v;
或者如果它们必须是数字:
v = +!v; /* Boolean invert v then cast back to a Number */
({v :+! v}).v
。 - pimvdb+
符号!¯\(ツ)/¯ - jAndyv
赋值为 (v ? 0 : 1)
是一种清晰、惯用的写法。 - Bennett McElweev = (v + 1) % 2
。如果你需要循环多个值,只需将2
替换为(n + 1)
即可。比如你需要循环0、1、2这三个值,只需写成v = (v + 1) % 3
。
const
变量来代替魔法数字 2、3 等等。 - oosterwal++v % 3
。 - haraldmartininv
函数应该填写什么呢:P)。 - Lea Hayesinv
是一个描述性的名称吗? - Bennett McElwee如果你只关心1这种情况,而不在意其他可能性:
v = v ? 0 : 1;
在上述情况中,如果v为0、false、undefined或null,则v最终将成为1。使用这种方法时要小心 - 即使v是“hello world”,v也将为0。v = v ? 0 : 1
。 - Guffa像 v = 1 - v
, v ^= 1
或者 v= +!v
这样的代码都可以实现要达到的效果,但是它们可以被称为“hack”。这些并不是优美的代码,而只是为了达到目的而采用的把戏。 1 - v
并不能清晰地表达“在0和1之间切换变量的值”的意思。这会使你的代码缺乏表达力,并引入了一个(虽然很小的)需要其他开发人员解析你代码的点。
相比之下,拥有一个像 v = toggle(v)
的函数可以在一瞥之间传达出意图。
v=1-v
没有传达切换的意思吗?" - Blindy1-v
的确可以表示开关状态,但这是它唯一能表示的意思。例如,它也可以表示一个在 v=1
处为零的线,或者以 v=0.5
为中心的镜像变换。从这个意义上说,它有些模糊不清。虽然知道 v
只可能是 0
或 1
限制了它的意义,但这也迫使其他开发人员(或者您未来的自己)在理解这条简单语句之前先要了解上下文。 v = toggle(v)
已经非常明确了。 - Rayv ^= 1
就非常清晰明了。我认为这就是 v ^= 1
和 v=1-v
的区别。前者是一个逻辑操作,后者是一个算术操作,我们试图表示的是一个逻辑概念而不是一个数学概念。请注意,不要改变原文意思。 - Matthew Readv ^= 1
,也存在一些歧义,因为它可以被解释为按位异或。 - Ray暗示最准确的解决方案是:如果它是0,则我要将其设置为1,否则将其设置为0。
v = dirac_delta(0,v)
首先,我得坦白:我把我的Delta函数搞混了。Kronecker delta可能更合适一些,但是因为我想要一个与域无关的东西(Kronecker delta仅用于整数),所以它们的差别并不大。不过实际上我本不应该使用Delta函数,而应该说:v = characteristic_function({0},v)
让我澄清一下。回忆一下,一个 函数 是一个三元组,(X,Y,f),其中 X 和 Y 是集合(分别称为 定义域 和 值域),f 是将每个 X 的元素映射到一个 Y 值的规则。我们通常把三元组写成 f:X → Y。给定 X 的一个子集,比如 A,有一个称为特征函数的函数,它是一个函数 χA: X → {0,1}(也可以看作是一个到更大值域如 ℕ 或 ℝ 的函数)。这个函数是通过以下规则定义的:
χA(x) = 1,如果 x ∈ A,并且 χA(x) = 0,如果 x ∉ A。
如果您喜欢真值表,那么它就是问题“元素 x 是否为集合 A 的元素?”的真值表。
因此,从这个定义可以看出,在这里需要特征函数,其中 X 是一个包含 0 的大集合,A = {0}。这是我应该写的。
现在来讲一下 delta 函数。为此,我们需要了解积分。要么您已经知道它,要么您不知道。如果您不知道,那么我在这里所说的也无法告诉您理论的细节,但我可以给出一个简短的摘要。一个对集合 X 的 测度 本质上是“使平均数起作用所必需的东西”。也就是说,如果我们有一个集合 X 和一个该集合上的测度 μ,那么存在一类称为 可测函数 的函数 X → ℝ,满足表达式 ∫X f dμ 有意义并且在某种模糊的意义下是 f 在 X 上的“平均值”。
给定一个集合的测度,可以为该集合的子集定义一种“测度”。这是通过将其特征函数的积分赋值给一个子集来完成的(假设它是可测函数)。这个值可能是无穷大或未定义的(两者有微妙的区别)。
有很多测度方法,但这里有两种比较重要。一种是定义在实数轴上的标准测度 ℝ。对于这种测度,∫ℝ f dμ 基本就是学校里教的内容(学校还教微积分吗?):把小矩形加起来,然后宽度越来越小。在这种测度下,区间的测度就是它的长度。点的测度是0。
另一种重要的测度可以用于任何集合,称为点测度。它被定义为函数的积分等于其值的和:
∫X f dμ = ∑x ∈X f(x)
这个测度将每个单点集的测度赋值为1。这意味着如果子集本身是有限的,那么它有有限的测量。非常少量的函数具有有限积分。如果一个函数有有限积分,则其仅在可数个点处非零。所以你可能知道的大多数函数在这种测度下没有有限积分。
现在来谈一谈狄拉克函数。让我们给出一个非常广泛的定义。我们有一个可测空间(X,μ)(即具有度量的集合)和一个元素a ∈ X。根据a,“定义”“delta函数”(δa)为具有以下特性的“函数”δa: X → ℝ:如果x ≠ a,则δa(x) = 0且∫X δa dμ = 1。
需要掌握的最重要的事实是:狄拉克函数不一定是函数。它没有被正确地定义:我并没有说明δa(a)是什么。
接下来要做的取决于您是谁。这里的世界分为两类人。如果你是数学家,你会说:
好的,这里的Delta函数可能没有被准确定义。让我们看看它的假设性质,并找到一个适当的定义它的位置。我们可以这样做,并且最终会得到分布。这些不一定是函数,但它们的行为有点像函数,通常我们可以像使用函数一样处理它们; 但是它们缺少某些东西(如“值”),因此我们需要小心。
如果您不是数学家,则可以说:
好的,那么Delta函数可能没有被准确定义。谁这么说?一群数学家?忽略他们!他们知道什么?
现在我已经冒犯了我的听众,所以我将继续。
Dirac Delta通常被认为是实线上一个点(通常为0)的delta函数及其标准测度。因此,那些在评论中抱怨我不知道我的delta的人之所以这样做是因为他们正在使用此定义。对于他们,我道歉:虽然我可以通过使用“数学家的辩护”(由Humpty Dumpty流行化)来摆脱这种情况:只需重新定义一切使其正确即可,但使用标准术语表示不同的含义是不恰当的。
但是,确实有一个Delta函数可以做到我希望它做的事情,这就是我在这里需要的。如果我对集合X进行一次点测度,则存在一个真实的函数δa:X→ ℝ满足delta函数的标准。这是因为我们正在寻找一个函数X → ℝ,它除了在a处为零以外,在其他地方都为零,并且其所有值的总和为1。这样的函数很简单:唯一缺少的信息是它在a处的值,为使总和为1,我们只需将其赋值为1。这就是单点集上的特征函数。然后:
∫X δa dμ = ∑x ∈ X δa(x) = δa(a) = 1.
因此,在这种情况下,对于单例集,特征函数和delta函数是相同的。
总之,这里有三个“函数”家族:
< p>其中第二个是最通用的,因为在使用点度量时其他任何选项都是它的示例。但是,第一个和第三个具有它们始终是真实函数的优势。第三个实际上是第一个的一个特殊情况,适用于特定的域族(整数或某些子集)。
- 单例集的特征函数,
- Delta函数,
- Kronecker Delta函数。
因此,最后,在我最初撰写答案时,我没有认真思考(我不会说我很困惑,因为我希望我刚刚展示了当我实际思考时我知道自己在说什么,只是我没有太多思考)。 Dirac delta的通常含义不是这里想要的,但是我的答案的一个要点是输入域未定义,因此Kronecker delta也不正确。 因此,最好的数学答案(我旨在)将是特性函数。
希望那一切都清楚; 我也希望我永远不必再次使用HTML实体而不是TeX宏来编写数学文章!
v = Math.abs(--v);
减量操作将值设置为0或-1,然后Math.abs
将-1转换为+1。
v = Math.round(Math.sin(Math.PI/(v+3)));
- Benoitv = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));
:D - Teo.skv = 1
,那么 v = Math.Abs(-1)
就是 +1。如果 v = 0
,那么 v = Math.Abs(-0)
就是 0。 - Paul通常情况下,当你需要在两个值之间切换时,只需将当前值从两个切换值的总和中减去:
0,1 -> v = 1 - v
1,2 -> v = 3 - v
4,5 -> v = 9 - v
v
变得损坏,它将突然开始在两个不同的值之间切换。(只是需要考虑一下...) - oosterwalv
通常用于从三个或更多状态的列表中交替执行两个状态,则v
的损坏可能导致程序交替执行两个完全不同的状态--这可能会导致意外和不良结果。从中得出的教训是:始终对您的数据执行合理性检查。 - oosterwal如果必须是整数1或0,那么你现在的做法没问题,尽管括号不是必需的。如果这些a要用作布尔值,那么你可以直接这样做:
v = !v;
v = +!v;
(注:该语句为计算机编程语言中的代码,意义为将变量v的值取反后再转换为数字类型并赋值给v) - jAndy