C# 当使用整数作为除数时,计算公式的最佳方法是什么
我经常发现自己有一个表达式,其中除以int是一个大公式的一部分。我将给你一个简单的例子来说明这个问题:C# 当使用整数作为除数时,计算公式的最佳方法是什么,c#,.net,C#,.net,我经常发现自己有一个表达式,其中除以int是一个大公式的一部分。我将给你一个简单的例子来说明这个问题: int a = 2; int b = 4; int c = 5; int d = a * (b / c); 在本例中,d如预期的那样等于0,但我希望它是1,因为4/5乘以2等于1 3/5,当转换为int get时,它的“舍入”为1。所以我发现自己必须将c转换为double,然后因为这使表达式也成为double,所以将整个表达式转换为int int a = 2; int b = 4; int
int a = 2;
int b = 4;
int c = 5;
int d = a * (b / c);
在本例中,d如预期的那样等于0,但我希望它是1,因为4/5乘以2等于1 3/5,当转换为int get时,它的“舍入”为1。所以我发现自己必须将c转换为double,然后因为这使表达式也成为double,所以将整个表达式转换为int
int a = 2;
int b = 4;
int c = 5;
int d = (int)(a * (b / (double)c));
// Probably you'd make this implement IEquatable<Term>, IEquatable<double>, etc.
// Probably you'd also give it a more descriptive, less ambiguous name.
// Probably you also just flat-out wouldn't use it at all.
struct Term
{
readonly double _value;
internal Term(double value)
{
_value = value;
}
public override bool Equals(object obj)
{
// You would want to override this, of course...
}
public override int GetHashCode()
{
// ...as well as this...
return _value.GetHashCode();
}
public override string ToString()
{
// ...as well as this.
return _value.ToString();
}
}
在这个小例子中,它并没有那么糟糕,但在一个大的公式中,它是相当混乱的
另外,我猜演员阵容会对表演产生(小)影响
所以我的问题基本上是,除了计算除数和结果,是否还有更好的方法
我知道在这个例子中,将a*(b/c)更改为(a*b)/c可以解决问题,但在更大的实际场景中,进行此更改是不可能的
编辑(从现有程序中添加案例):
在本例中,我根据滚动条的大小及其容器的大小计算滚动条的位置。因此,如果页面上有两个元素要适合,滚动条将是容器高度的一半,如果我们滚动了可能的一半元素,这意味着滚动器位置应该向下移动1/4,这样它将驻留在容器的中间。计算工作正常,显示良好。我只是不喜欢我的代码中的表达式
代码的重要部分放在这里并附加在这里:
int scrollerheight = (menusize.Height * menusize.Height) / originalheight;
int maxofset = originalheight - menusize.Height;
int scrollerposition = (int)((menusize.Height - scrollerheight) * (_overlayofset / (double)maxofset));
这里的originalheight是所有元素的高度,因此在上述情况下,这将是menusize.height的两倍。首先,C#截断int除法的结果,当转换为int时,没有舍入
如果不进行任何转换,就不可能先进行b/c转换。免责声明:我把所有这些都打出来了,然后我想,我应该发布这些吗?我的意思是,这是一个非常糟糕的想法,因此对手术没有帮助。。。最后我想,嘿,我已经把它都打出来了;我不妨继续点击“发布你的答案”。尽管这是一个“坏”主意,但还是有点有趣(无论如何,对我来说)。所以也许你会从中受益 出于某种原因,我怀疑上述免责声明不会保护我不受反对票的影响,尽管
这是一个完全疯狂的想法。 实际上,我不建议将其应用于任何类型的生产环境,因为我刚才确实想到了它,这意味着我还没有真正彻底地考虑过它,我确信它存在大约10亿个问题。这只是一个想法 但基本概念是创建一个可用于算术表达式的类型,在内部为表达式中的每个术语使用一个
double
,最后只作为所需的类型进行计算(在本例中:int
)
您可以从以下类型开始:
int a = 2;
int b = 4;
int c = 5;
int d = (int)(a * (b / (double)c));
// Probably you'd make this implement IEquatable<Term>, IEquatable<double>, etc.
// Probably you'd also give it a more descriptive, less ambiguous name.
// Probably you also just flat-out wouldn't use it at all.
struct Term
{
readonly double _value;
internal Term(double value)
{
_value = value;
}
public override bool Equals(object obj)
{
// You would want to override this, of course...
}
public override int GetHashCode()
{
// ...as well as this...
return _value.GetHashCode();
}
public override string ToString()
{
// ...as well as this.
return _value.ToString();
}
}
接下来,定义操作本身:加上
,减去
,等等。对于示例代码,我们需要次
(对于*
)和除以
(对于/
):
最后,编写一个static
helper类,使您能够对想要使用的任何类型(可能只是int
)执行基于Term
的操作:
这一切能给你带来什么<几乎什么都没有但它会清理您的表达式,隐藏所有难看的显式强制转换,使您的代码更具吸引力,也更不可能调试。(再一次,这不是认可,只是一个疯狂的想法。)
因此,与此相反:
int d = (int)(a * (b / (double)c)); // Output: 2
你会有这个:
int d = a.Times(b.DividedBy(c)); // Output: 2
值得吗?
好吧,如果不得不编写强制转换操作是世界上最糟糕的事情,比如,甚至比依赖过于聪明的代码更糟糕,那么也许这样的解决方案值得追求
由于上述情况显然不是真的。。。答案是一个非常明确的否定。但我想我还是要分享这个想法,以证明这样的事情(也许)是可能的。将b乘以100。然后在末尾除以100。在这种情况下,我建议使用双精度,因为不需要精确的精度
但是,如果您真的想在不使用浮点运算的情况下完成这一切,我建议您创建某种分数类,它要复杂得多,效率要低得多,但您可以跟踪所有的除数和除数,然后一次计算所有除数和除数。如果一个明显的解决方案(模溢出)不适用于您的实际情况,也许你可以举一个真实案例的例子。否则,我们的任何建议都可能同样无效。我在上面的问题上添加了一个编辑,给出了一个来自当前程序的示例(实际上是让我首先写这个问题的示例:))如果你知道你需要float/double,为什么要使用int?计算中的任何元素都不需要float/double,也不是它的结果。问题是,由于_overlayofset在所有情况下都小于maxofset,如果没有此强制转换,结果将始终计算为0。我同意你的观点。也许不值得,但这是一个非常有趣的思想实验。感谢您花时间完成所有这些工作。这当然会起作用,但在代码中看起来会更加混乱。再乘以100,再除以100,我的性能会比两次强制转换更高,所以我觉得这个解决方案比当前实现的解决方案差。是的。一个double当然可以,但是我想知道是否有使用int的解决方案,但是我开始认为这是不好的
int d = a.Times(b.DividedBy(c)); // Output: 2