三元运算在 Octave 中有效吗?
Is Ternary operation valid in Octave?
问题是有效的三元运算,因为我无法在网上找到任何相关文档。而且我还发现在 MATLAB 中不可能使用三元,所以任何建议和答案将不胜感激。
#三元运算的代码
taxes = (income > 50000)*(((income-50000) * 0.20)+(0.10*50000)) + (~(income > 50000))*0.10 *50000
#Condition True and this computation False then this computation
#用 if 和 else 编码
if (income) > 50000
#income = income - 50000
#Taxed at 10% (i.e 0.10) for $ 50000
#taxes = 50000 * 0.10
#Rest income will be Taxed at 20% (i.e 0.20)
taxes = 50000 * 0.10 + ((income-50000) * 0.20)
else
#Taxed at 10% (i.e 0.10)
taxes = income * 0.10
endif
输出:
GNU Octave, version 6.1.0
Copyright (C) 2020 The Octave Project Developers.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. For details, type 'warranty'.
Octave was configured for "x86_64-w64-mingw32".
Additional information about Octave is available at https://www.octave.org.
Please contribute if you find this software useful.
For more information, visit https://www.octave.org/get-involved.html
Read https://www.octave.org/bugs.html to learn how to submit bug reports.
For information about changes from previous versions, type 'news'.
>> income = 60000;
>> compute_taxes
taxes = 7000
>> income = 50000;
>> compute_taxes
taxes = 5000
>>
任何语言中三元运算符的任何定义与 if 语句.
之间存在一些重要差异
主要是后者是一个语句,而三元运算符根据定义是一个表达式。换句话说,你期望它给return一个值。 octave/matlab 中的 if 块不会“return”一个值(即你不能做 a = if ... endif
)。如果你需要一些东西'returned',你需要在循环内将它赋给一个外部变量,然后在循环外使用那个变量。
第二件大事,三元运算符应该可链接。也就是说,您应该能够做到“如果这样,那么那样,否则如果那样,那么其他事情”,这样在一长串比较的末尾,您 return 一个值。
现在octave和matlab都没有这种算子。但是在八度音程中,很容易模拟一个,例如使用单元格:
M1 = false; M2 = false; M3 = true;
{'expression1', 'expression2', 'expression3', 'fallback'}([ M1, M2, M3, true ]){1}
如果你真的想要,你可以把那种东西变成一个很好的匿名函数,return它是第一个 mask/test 为真的表达式:
tern = @(varargin) reshape(varargin,2,[])(2,:)([reshape(varargin,2,[]){1,:}]){1}
tern( M1, 1, M2, 2, M3, 3, true, 4 ) % ans = 3
其中 'fallback' 只需通过在 'fallback' 值之前明确评估为 'true' 的测试来实现。
注意:这种 'chaining' 匿名函数中的两个或多个索引操作的样式仅适用于八度音阶,不幸的是 matlab 不允许链式操作,例如a(1)(2)
。没有什么能阻止你创建一个等价的 'proper' 外部函数,你可以在第二次索引之前将中间结果保存到一个临时变量中;因此,从概念上讲,该策略也适用于 matlab。
或者,您可以使用稍微不同的语法创建更简单的 'ternary operator'(好吧,函数),其中您传递一个 'tests/masks' 数组、'expressions' 和 'fallback' 细胞分开。例如
tern2 = @(M,E,F) [E, F]{find([M, true], 1)}
tern2( [M1, M2, M3], {1, 2, 3}, {4} ) % ans = 3
最后,还有ifelse
函数,它在本质上是相似的,即ifelse(test, expr_if_true, expr_if_false)
,但这并不是真正的三元operator/function,因为它是不可链接的;根据 'true/false mask' 在两个备选方案之间进行选择更有用,例如
ifelse( [M1, M2, M3], {1, 2, 3}, {4,5,6} )
% ans = { 4, 5, 3 }
你可以用两个短路&&
和||
运算符来模拟三元if
运算符。
考虑这个 if/else
语句:
if condition
val = expr1;
else
val = expr2;
end
将 t
定义为 t = @(x) 1;
并将三元 if
运算符定义为:
condition && t(val = expr1) || t(val = expr2);
实现三元 if
运算符的一个重点是表达式 expr1
和 expr2
的计算。如果 condition
是 true
,则不能计算 expr2
,如果 condition
是 false
,则不能计算 expr1
。在像 ifelse/merge
这样的函数中,两个表达式在传递给函数之前都会被求值,因此 ifelse
不应被视为真正的三元 if
运算符。
有一些基于 MATLAB 的实现 and 用于创建递归匿名函数。诀窍是表达式被 lambda 包裹起来以防止对其求值。
考虑以下计算第 n 个斐波那契数的函数:
function val = fib(f, n)
if n <= 2
val = 1;
else
val = f(f, n - 1) + f(f, n - 2));
end
当前提议的技术可用于实现它(在 Octave 6.1.0 上测试):
fib = @(f, n, t = @(x) 1, tmp = n <= 2 && t(val = 1) || t(val = f(f, n - 1) + f(f, n - 2))) val;
在递归匿名函数以外的情况下你可以使用这个:
val = {condition && t(tmp = expr1) || t(tmp = expr2), tmp}{2};
然而,这些技巧可能不会比 if/else
语句更好。
考虑实现三元条件运算符函数
不知道 matlab 版本是否可以处理字符串和数组,因为这个可以
clear ternary
function tern = ternary( test, alternatives);
if length( alternatives(:,1)) == 1,, alternatives = alternatives(:); end;
if test,, tern = alternatives(1,:);
else, tern = alternatives(2,:); end
return; end;
一些示例调用
methodss = ['Runge-Kutta'; 'Adams-MLS'];
adaptive_step = ['adaptive step control'; 'fixed step size'];
report_method = @(selectmethod) [char( ternary (selectmethod(1), methodss )) ' ' ...
char( ternary (selectmethod(2), adaptive_step)) ];
%
report_method( [true false]),; % self-starting = true ; adaptive step size = false
report_method( [false true ]),; % self-starting = false; adaptive step size = true
% ans = Runge-Kutta fixed step size
% ans = Adams-MLS adaptive step control
ternary(2 > 2, [123 456]) % 456
ternary(2 >= 2, [123 456]) % 123
ternary(2 > 2, [123 456; 789 999]) % 789 999
ternary(2 >= 2, [123 456; 789 999]) % 123 456
问题是有效的三元运算,因为我无法在网上找到任何相关文档。而且我还发现在 MATLAB 中不可能使用三元,所以任何建议和答案将不胜感激。
#三元运算的代码
taxes = (income > 50000)*(((income-50000) * 0.20)+(0.10*50000)) + (~(income > 50000))*0.10 *50000
#Condition True and this computation False then this computation
#用 if 和 else 编码
if (income) > 50000
#income = income - 50000
#Taxed at 10% (i.e 0.10) for $ 50000
#taxes = 50000 * 0.10
#Rest income will be Taxed at 20% (i.e 0.20)
taxes = 50000 * 0.10 + ((income-50000) * 0.20)
else
#Taxed at 10% (i.e 0.10)
taxes = income * 0.10
endif
输出:
GNU Octave, version 6.1.0
Copyright (C) 2020 The Octave Project Developers.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. For details, type 'warranty'.
Octave was configured for "x86_64-w64-mingw32".
Additional information about Octave is available at https://www.octave.org.
Please contribute if you find this software useful.
For more information, visit https://www.octave.org/get-involved.html
Read https://www.octave.org/bugs.html to learn how to submit bug reports.
For information about changes from previous versions, type 'news'.
>> income = 60000;
>> compute_taxes
taxes = 7000
>> income = 50000;
>> compute_taxes
taxes = 5000
>>
任何语言中三元运算符的任何定义与 if 语句.
之间存在一些重要差异主要是后者是一个语句,而三元运算符根据定义是一个表达式。换句话说,你期望它给return一个值。 octave/matlab 中的 if 块不会“return”一个值(即你不能做 a = if ... endif
)。如果你需要一些东西'returned',你需要在循环内将它赋给一个外部变量,然后在循环外使用那个变量。
第二件大事,三元运算符应该可链接。也就是说,您应该能够做到“如果这样,那么那样,否则如果那样,那么其他事情”,这样在一长串比较的末尾,您 return 一个值。
现在octave和matlab都没有这种算子。但是在八度音程中,很容易模拟一个,例如使用单元格:
M1 = false; M2 = false; M3 = true;
{'expression1', 'expression2', 'expression3', 'fallback'}([ M1, M2, M3, true ]){1}
如果你真的想要,你可以把那种东西变成一个很好的匿名函数,return它是第一个 mask/test 为真的表达式:
tern = @(varargin) reshape(varargin,2,[])(2,:)([reshape(varargin,2,[]){1,:}]){1}
tern( M1, 1, M2, 2, M3, 3, true, 4 ) % ans = 3
其中 'fallback' 只需通过在 'fallback' 值之前明确评估为 'true' 的测试来实现。
注意:这种 'chaining' 匿名函数中的两个或多个索引操作的样式仅适用于八度音阶,不幸的是 matlab 不允许链式操作,例如a(1)(2)
。没有什么能阻止你创建一个等价的 'proper' 外部函数,你可以在第二次索引之前将中间结果保存到一个临时变量中;因此,从概念上讲,该策略也适用于 matlab。
或者,您可以使用稍微不同的语法创建更简单的 'ternary operator'(好吧,函数),其中您传递一个 'tests/masks' 数组、'expressions' 和 'fallback' 细胞分开。例如
tern2 = @(M,E,F) [E, F]{find([M, true], 1)}
tern2( [M1, M2, M3], {1, 2, 3}, {4} ) % ans = 3
最后,还有ifelse
函数,它在本质上是相似的,即ifelse(test, expr_if_true, expr_if_false)
,但这并不是真正的三元operator/function,因为它是不可链接的;根据 'true/false mask' 在两个备选方案之间进行选择更有用,例如
ifelse( [M1, M2, M3], {1, 2, 3}, {4,5,6} )
% ans = { 4, 5, 3 }
你可以用两个短路&&
和||
运算符来模拟三元if
运算符。
考虑这个 if/else
语句:
if condition
val = expr1;
else
val = expr2;
end
将 t
定义为 t = @(x) 1;
并将三元 if
运算符定义为:
condition && t(val = expr1) || t(val = expr2);
实现三元 if
运算符的一个重点是表达式 expr1
和 expr2
的计算。如果 condition
是 true
,则不能计算 expr2
,如果 condition
是 false
,则不能计算 expr1
。在像 ifelse/merge
这样的函数中,两个表达式在传递给函数之前都会被求值,因此 ifelse
不应被视为真正的三元 if
运算符。
有一些基于 MATLAB 的实现
考虑以下计算第 n 个斐波那契数的函数:
function val = fib(f, n)
if n <= 2
val = 1;
else
val = f(f, n - 1) + f(f, n - 2));
end
当前提议的技术可用于实现它(在 Octave 6.1.0 上测试):
fib = @(f, n, t = @(x) 1, tmp = n <= 2 && t(val = 1) || t(val = f(f, n - 1) + f(f, n - 2))) val;
在递归匿名函数以外的情况下你可以使用这个:
val = {condition && t(tmp = expr1) || t(tmp = expr2), tmp}{2};
然而,这些技巧可能不会比 if/else
语句更好。
考虑实现三元条件运算符函数
不知道 matlab 版本是否可以处理字符串和数组,因为这个可以
clear ternary
function tern = ternary( test, alternatives);
if length( alternatives(:,1)) == 1,, alternatives = alternatives(:); end;
if test,, tern = alternatives(1,:);
else, tern = alternatives(2,:); end
return; end;
一些示例调用
methodss = ['Runge-Kutta'; 'Adams-MLS'];
adaptive_step = ['adaptive step control'; 'fixed step size'];
report_method = @(selectmethod) [char( ternary (selectmethod(1), methodss )) ' ' ...
char( ternary (selectmethod(2), adaptive_step)) ];
%
report_method( [true false]),; % self-starting = true ; adaptive step size = false
report_method( [false true ]),; % self-starting = false; adaptive step size = true
% ans = Runge-Kutta fixed step size
% ans = Adams-MLS adaptive step control
ternary(2 > 2, [123 456]) % 456
ternary(2 >= 2, [123 456]) % 123
ternary(2 > 2, [123 456; 789 999]) % 789 999
ternary(2 >= 2, [123 456; 789 999]) % 123 456