你会如何重构这段代码?你会如何重构这段代码?
double p = (Convert.ToDouble(inta)/Convert.ToDouble(intb)) * 100;
double v = (p/100) * Convert.ToDouble(intc);
return (int)v;
看起来很凌乱我,我知道我可以挤在同一行,但我很想知道别人会怎么做。
由于
你会如何重构这段代码?你会如何重构这段代码?
double p = (Convert.ToDouble(inta)/Convert.ToDouble(intb)) * 100;
double v = (p/100) * Convert.ToDouble(intc);
return (int)v;
看起来很凌乱我,我知道我可以挤在同一行,但我很想知道别人会怎么做。
由于
假设inta
,intb
和intc
被分类为int
/Int32
然后Convert.ToDouble
是基本相同的简单铸造到double
。
return (int)((inta/(double)intb) * intc);
这实际上是否值得重构是另一回事。即使您不需要这些中间结果,将中间计算作为单独的语句来提高可读性通常也更有意义。当然,具有有意义的变量名称使大的区别。
+1 - 打我的答案,以及添加一些务实的建议。 – ChaosPandion 2010-11-08 22:38:42
return (int)(Convert.ToDouble(inta * intc)/Convert.ToDouble(intb));
return (int)(((double)inta/intb) * intc);
(固定)
不会。进行整数除法 – 2010-11-08 22:27:18
哎呀,我的(双重)演员在括号的错误一侧 – 2010-11-08 22:39:44
只需将其删除;使用您的编辑,它与接受的答案相同 – 2010-11-09 00:35:27
严重的是,没有。代码有什么问题,因为它 - 忽略可能的数学问题和只是看着代码结构本身?
我不会重构。把它全部挤在一条线上会使阅读困难得多。如果我绝对必须做一些事情,我会为A,B和C的这样的双版本创建新的变量:
//set up variables
double doubleA = Convert.ToDouble(inta);
double doubleB = Convert.ToDouble(intb);
double doubleC = Convert.ToDouble(intc);
//do calculations
double p = (doubleA/doubleB) * 100
double v = (p/100) * doubleC; //why did we divide by 100 when we multiplied by it on the line above?
return (int)v; //why are we casting back to int after all the fuss and bother with doubles?
但实际上我宁愿只是不要管它!
我会给变量一个更有意义的名称,除此之外,这对我来说也是+1 – Zac 2010-11-08 22:49:03
@Zac:我也想要更多有意义的名字,但在这种情况下,不可能知道它们的真实含义。 – FrustratedWithFormsDesigner 2010-11-09 04:27:34
首先我会给p,v,inta,intb等有意义的名字。
前两行可以组合:
double pv = ((double)inta/intb)*intc;
return (int)pv;
+1对于有意义的名称 – egrunin 2010-11-08 22:41:23
我将它们重命名为张贴在这里!谢谢 – 2010-11-08 22:47:39
上@ FrustratedWithFormsDes的答案的变化:
double doubleA = (double) (inta * intc);
double doubleB = (double) intb;
return (int) (doubleA/doubleB);
有几个有趣的点,没有其他人似乎已经覆盖了,所以我会加进来......
所以(假设非巨大的国际价值,并接受我们可能会抛出一个div被零除外)的最终结果(而不是重命名为清楚起见)可能是:
return((int) ((inta * intc)/(double) intb));
这不是与接受的答案有很大的不同,但在某些平台上可能会稍微好一些(通过使用整数乘法而不是双重算法)。
那么,首先我会使用更有意义的名称,并且猜测这是一个整数比率,将其转换为百分比,将该百分比应用于另一个原始值,并返回一个新值是截断为整数的结果。
double percent = (Convert.ToDouble(numer)/Convert.ToDouble(denom)) * 100;
double value = (percent/100) * Convert.ToDouble(originalValue);
return (int)value;
一个使用转换和模具之间的区别是,转换将抛出一个异常的出界,但铸造不会和铸造为int的Int32.MinValue结果。因此,如果value
对于int或Infinity
或NaN
太大或太小,您将在末尾获得Int32.MinValue而不是异常。其他转换器不能失败,因为任何int都可以表示为double。
所以,你可以使用强制转换与意义没有改变它写,并利用表达式中的涉及整数和双打的整数自动转换为双打的事实:
double percent = ((double) numer)/denom) * 100;
double value = (percent/100) * originalValue;
return (int)value;
现在,C#截断双重结果分配给15-16,但它的实现定义了中间体是否以更高的精度运行。我不认为这会改变可以转换为int的范围内的输出,但我不知道,而且值空间对于穷举测试来说太大了。因此,如果没有关于的规范,这个函数打算做什么,那么您可以更改的内容很少,并且确保您不会更改输出。
如果你比较这些重构,其中的每一个天真的数学等价的,并且贯穿其中值的范围:
static int test0(int numer, int denom, int initialValue)
{
double percent = (Convert.ToDouble(numer)/Convert.ToDouble(denom)) * 100;
double value = (percent/100) * Convert.ToDouble(initialValue);
return (int)value;
}
static int test1(int numer, int denom, int initialValue)
{
return (int)((((((double)numer)/denom) * 100)/100) * initialValue);
}
static int test2(int numer, int denom, int initialValue)
{
return (int)((((double)numer)/denom) * initialValue);
}
static int test3(int numer, int denom, int initialValue)
{
return (int)((((double)numer) * initialValue)/denom);
}
static int test4(int numer, int denom, int initialValue)
{
if (denom == 0) return int.MinValue;
return (numer * initialValue/denom);
}
那么你得到计数的时间testN
数以下结果不等于test0
并让它运行几个小时:
numer in [-10000,10000]
denom in [-10000,0) (0,10000]
initialValue in [-10000,-8709] # will get to +10000 eventually
test1 fails = 0 of 515428330128 tests, 100% accuracy.
test2 fails = 110365664 of 515428330128 tests, 99.9785875828803% accuracy.
test3 fails = 150082166 of 515428330128 tests, 99.9708820495057% accuracy.
test4 fails = 150082166 of 515428330128 tests, 99.9708820495057% accuracy.
所以,如果你想要一个完全等效的功能的话,好像是你可以得到test1
。虽然100s应该在test2
中取消,但实际上它们在几个边缘情况下会影响结果 - 中间值的四舍五入将值推向整数的一侧或另一侧。对于此测试,输入值在-10000至+10000之间,因此test4
中的整数乘法不会溢出,因此test3
和test4
是相同的。对于更宽的输入范围,test4会更频繁地出现偏差。
始终验证您的重构是否针对自动化测试。不要以为计算机的价值观就像高中数学中的数字一样。
下面的一些答案令我难过。 :*(他说重构,而不是反射器 – 2010-11-08 22:26:43
真的很奇怪的是,使用双打给你四舍五入的错误 – Ishtar 2010-11-08 22:53:22