![](/img/trans.png)
[英]An efficient way to perform an all reduction in MPI of a value based on another variable?
[英]Efficient way to set a group of variables based on another variable?
我想设置一组2-4个变量,它们的值取决于第5个变量。 我可以通过一长串的if else
来做到这一点,我想知道是否有一个我不知道可以学到的技巧,可以更优雅地做到这一点? 我对``C.
例如:
/*some code... x is read from stdin...*/
if (x == 1) {
a = 10;
b = 100;
}
else if (x == 2) {
a = 10;
b = 50;
c = 100;
}
else if (x == 3) {
a = 0;
b = 25;
c = 50;
d = 100;
}
/* and so on...*/
我打算使用指针来设置a
, b
, c
...,而不是通过main()
函数来完成所有操作,但是为了简单起见,这里省略了它。
干杯,
w ^
好吧, switch
语句通常比一堆if-else
语句更优雅
switch (x) {
case 1: a = 10;
b = 100;
break;
case 2: a = 10;
b = 50;
c = 100;
break;
case 3: a = 0;
b = 25;
c = 50;
d = 100;
break;
default: // have a default case or catch it as an error
}
如果您真的很想让这段代码简短易读,则可以通过使用函数来设置变量来进一步加紧代码。
switch (x) {
case 1: caseA(&a, &b);
break;
case 2: caseB(&a, &b, &c);
break;
case 3: caseC(&a, &b, &c, &d);
break;
default: // have a default case or catch it as an error
}
void caseA(int *a, int *b) {
*a = 10;
*b = 100;
}
您可以使用switch(x)
,如果一些值具有相同的效果,则将允许您回收某些代码。 例如
switch(x){
case 5:
case 6:
a=0;
b=25; //this code will run for both cases
}
当然有限制。 您不能真正将其应用于所有情况。
同样,通过使用三元运算符,您可以处理一些临界情况。 想象一下,例如,每次x==2
时a=10
,那么它就是5。 因此,您可以像这样处理单个变量: a = (x==2)?5:10;
以我的方式,将数据与程序功能区分开来的价值是:
int data[3][4] = {
{10, 100, 0, 0},
{10, 50, 100, 0},
{0, 25, 50, 100}
};
a
, b
, c
和d
成为此数组的特定行,您可以使用该行对其进行索引
data[-1 + x]
static const int a[4] = {10, 10, 0};
static const int b[4] = {100, 50, 25};
static const int c[4] = {0, 100, 50};
static const int d[4] = {0, 0, 100};
printf("%d %d %d %d\n", a[x - 1], b[x - 1], c[x - 1], d[x - 1]);
或使用数学,并要牢记以下特定值:
// if (x == 1){a = 10; b = 100;}
// else if (x == 2){a = 10; b = 50; c = 100;}
// else if (x == 3){a = 0; b = 25; c = 50; d = 100;}
void get_values(int x, int *a, int *b, int *c, int *d)
{
*a = (1 - x / 3) * 10;
*b = 100 >> (x - 1);
*c = (x - 1) * (200 >> (x - 1));
*d = (x / 3) * 10;
}
int main(void)
{
int a, b, c, d;
int x = 3;
get_values(x, &a, &b, &c, &d);
printf("%d %d %d %d\n", a, b, c, d);
return (0);
}
通常将比上述所有解决方案都要快,因为编译器无法进行这些超具体的优化,但这取决于您的需求。 同样,最后一个虽然最快,但肯定会损害可读性,因此您应将计算值保留为注释。
如果x
值实际上是连续的,则可以创建一个结构数组来保存a,b,c,d的值。 唯一的技巧是,您需要一个哨兵值来指示不应设置变量。 在下面的示例中,值-1是前哨值。
struct setting
{
int a, b, c, d;
}
settings[] =
{
{ 0, 0, 0, 0 }, // x = 0 not used
{ 10, 100, -1, -1 }, // -1 indicates that a variable should be skipped
{ 10, 50, 100, -1 },
{ 0, 25, 50, 100 },
};
static int maxSetting = sizeof(settings) / sizeof(settings[0]);
void updateSettings(int x, int *a, int *b, int *c, int *d)
{
if (x > 0 && x < maxSetting)
{
struct setting *sptr = &settings[x];
if (sptr->a >= 0)
*a = sptr->a;
if (sptr->b >= 0)
*b = sptr->b;
if (sptr->c >= 0)
*c = sptr->c;
if (sptr->d >= 0)
*d = sptr->d;
}
}
如果您想黑客入侵,可以尝试以下技巧:
typedef enum
{
CASE_1_ = 1,
CASE_2_,
CASE_3_
}states;
void caseA(int *a, int *b, int *c, int *d) {
*a = 10;
*b = 100;
}
typedef void (*fp)(int *, int *, int *, int *);
fp proccess[] = {[CASE_1_] = caseA, [CASE_3_] = caseB, [CASE_3_] = caseC};
您需要做的只是proccess[x]();
,并且您不需要任何switch
或if-else
语句。
只是为了好玩,如果您现在想使事情复杂化,但是在多种情况下使您的生活更轻松,我有一个解决方案,乍一看很难实施,但是我喜欢它在可伸缩性和可扩展性方面的工作方式。可重用性。
以下代码以交互方式用于测试目的,丢弃您认为不需要的所有内容。
#include<stdio.h>
// Lets get handlers for each value
int f_One(void);
int f_Two(void);
int f_Three(void);
int f_Four(void);
// Lets have them in an enum rather than mere numbers, may not be required for you
typedef enum {
ONE = 1,
TWO,
THREE,
FOUR,
MAX_TASKS,
TASK_INVALID = -1,
} eValue_t ;
// This is a structure that binds an input and a handler together
typedef struct stTask {
eValue_t TaskID;
int (*handler) (void);
} stTask_t;
// Lets have an object
stTask_t Task;
// This is a like look-up table for referencing inputs and their handlers
const stTask_t TaskList[MAX_TASKS-1] =
{
{ ONE, f_One },
{ TWO, f_Two },
{ THREE, f_Three },
{ FOUR, f_Four },
};
// This is your data
int a, b, c, d;
// Handler for 1
int f_One(void)
{
printf("\nOne: ");
a = 10;
b = 100;
printf("a is %d, b is %d", a, b);
return 1;
}
// Handler for 2
int f_Two(void)
{
printf("\nTwo: ");
a = 10;
b = 50;
c = 100;
printf("a is %d, b is %d, c is %d", a, b, c);
return 2;
}
// Handler for 3
int f_Three(void)
{
printf("\nThree: ");
a = 0;
b = 25;
c = 50;
d = 100;
printf("a is %d, b is %d, c is %d, d is %d", a, b, c, d);
return 3;
}
// Handler for 4
int f_Four(void)
{
printf("\nFour: I didn't set any :D");
return 4;
}
int main (void)
{
int Val = -1;
int ret = 0;
while(1)
{
// Get input
printf("\n\nPress 1, 2, 3, 4 or 0 for exit, Enter a value: ");
scanf("%d", &Val);
// Some validation, can be improved, or discarded
if(Val > 4)
{
printf("\nInvalid input");
continue;
}
else if(Val == 0)
{
printf("\nExiting...");
break;
}
// Assign the task
Task.TaskID = Val-1;
// Load the handler
Task.handler = TaskList[Task.TaskID].handler;
// Execute the handler
ret = Task.handler();
// Do something with 'ret'
}
printf("\n\n");
return 0;
}
可以将枚举与union
使用。 结构的大小始终是最大的内容结构之一。
enum type
{
BAR = 0,
BAZ,
OTHER,
};
struct bar
{
int x;
char y;
};
struct baz
{
void * x;
float y;
};
struct other
{
char x[2];
};
typedef struct _foo
{
enum type type;
union
{
struct bar bar;
struct baz baz;
struct other other;
};
} foo;
...
struct bar a = { 1, 'c', };
foo x;
x.type = BAR;
x.bar = a;
struct baz b = { NULL, 1.0f, };
foo y;
y.type = BAZ;
y.baz = b;
if (x.type == BAR)
printf("%d\n", x.bar.x);
if (y.type == BAZ)
printf("%p\n", y.baz.x);
仅出于纯粹的乐趣,您就可以使用可变参数函数。 这是一个可能的方法(通过使用示例,您可以轻松地将其放入if
阶梯中):
#include <stdarg.h>
#include <stdio.h>
void set_bunch(int n_vars, ...) {
va_list args;
va_start(args, n_vars);
for (int i = 0; i < n_vars; ++i) {
int* varp = va_arg(args, int*);
int varv = va_arg(args, int);
*varp = varv;
}
va_end(args);
}
int main() {
int a, b, c, d;
set_bunch(2, &a, 20, &b, 30);
printf("%d %d\n", a, b); // prints 20 30
set_bunch(3, &a, 30, &b, 40, &c, 50);
printf("%d %d %d\n", a, b, c); // prints 30 40 50
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.