What is the best way to calculate a formula when using int as a divisor

Often I find that I have an expression where division by int is part of a large formula. I will give you a simple example illustrating this problem:

int a = 2; int b = 4; int c = 5; int d = a * (b / c); 

In this case, d is 0, as expected, but I would like it to be 1, since 4/5 times 2 is 1 3/5, and when converting to int it turns out “rounded” to 1. Thus , I discovered to merge c to double, and then, since this does the double expression as well, casting the entire expression into int. This code is as follows:

 int a = 2; int b = 4; int c = 5; int d = (int)(a * (b / (double)c)); 

In this small example, it is not so bad, but in a large formula it becomes rather dirty.

Also, I think casting will have a (small) impact on performance.

So my question is mainly if there is a better approach to this than listing both the divisor and the result.

I know that in this example, changing a * (b / c) to (a * b) / c will solve the problem, but in larger real-life scenarios this change will not be possible.

EDIT (case added from existing program):

In this case, I omit the position of the scroll bar according to the size of the scroll bar and the size of its container. Therefore, if there are two elements on the page that will fit on the page, the scroll bar will be half the height of the container, and if we scroll half the elements, this means that the position of the scroller should be moved 1/4 down, so it will be in middle of the container. The calculations work as they should, and it displays well. I just don't like how the expression looks in my code.

Important pieces of code are added and added here:

 int scrollerheight = (menusize.Height * menusize.Height) / originalheight; int maxofset = originalheight - menusize.Height; int scrollerposition = (int)((menusize.Height - scrollerheight) * (_overlayofset / (double)maxofset)); 

originalheight is the height of all elements, so in the case described above, it will be double of menusize.Height.

+4
source share
4 answers

First of all, C # truncates the result of int-division, and when casting to int. No rounding.

There is no way to do b / c first without any conversions.

+1
source

Disclaimer I typed all this and then I thought: “Should I even publish this? I mean, this is a pretty bad idea, and therefore it doesn’t really help the OP ... In the end, I realized that I already typed all this ; I could also go ahead and click “Post your answer.” Although this is a “bad” idea, it seems to be interesting (for me, anyway). So maybe some strange way will come in handy by reading it.

For some reason, I have a suspicion that the above disclaimer is not going to protect me from downvotes, though ...


Here is a completely crazy idea.

In fact, I would not recommend putting it in any production environment at all , because I literally thought about it just now, which means that I really did not think about it completely, and I'm sure that about a billion problems. This is just an idea.

But the basic concept is to create a type that can be used for arithmetic expressions that internally use double for each term in the expression, only to be evaluated as the desired type (in this case: int ) at the end.

You will start with a type like:

 // 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(); } } 

Then you define the implicit conversions to / from double and the types (s) you want to support (again: int ). Like this:

 public static implicit operator Term(int x) { return new Term((double)x); } public static implicit operator int(Term x) { return (int)x._value; } // ...and so on. 

Then define the operations themselves: Plus , Minus , etc. For your example code, we need Times (for * ) and DividedBy (for / ):

 public Term Times(Term multiplier) { // This would work because you would've defined an implicit conversion // from double to Term. return _value * multiplier._value; } public Term DividedBy(Term divisor) { // Same as above. return _value / divisor._value; } 

Finally, write a helper class static , so that you can perform operations with Term on all types that you want to work with (perhaps only int for starters):

 public static class TermHelper { public static Term Times(this int number, Term multiplier) { return ((Term)number).Times(multiplier); } public static Term DividedBy(this int number, Term divisor) { return ((Term)number).DividedBy(divisor); } } 

What would you buy all this? Almost nothing! But it will clear your expressions, hide all these unsightly explicit casts, making your code much more attractive and much more impossible to debug. (Once again, this is not an endorsement , just a crazy idea).

So instead:

 int d = (int)(a * (b / (double)c)); // Output: 2 

You will have the following:

 int d = a.Times(b.DividedBy(c)); // Output: 2 

Is it worth it?

Well, if writing casting operations were the worst in the world, for example, even worse than relying on code that is too smart for its own good, then perhaps such a solution would be appropriate.

Since the above is clearly not true ... the answer is quite expressive NO . But I just thought that I would share this idea anyway to show that such a thing is (possibly) possible.

+2
source

Multiply b times 100. Then divide by 100 at the end.

+1
source

In this case, I would suggest using double instead, because you don't need accurate precision.

However, if you really feel that you want to do all this without a floating point operation, I would suggest creating some kind of fraction class that is much more complicated and less efficient, but you can track all the dividends and dividers and then calculate everything at once.

+1
source

All Articles