optimize code to get the number of integers within given range that are divisible by integer

你离开我真会死。 提交于 2019-12-23 09:49:18

问题


Given range x, y. I need to count all numbers in between and are divisible by n.

I know the simple way to do this is by looping over the whole range

for(int i=x;i<=y;i++) if(i%n ==0) counter++; 

The counter holds the answer.

But this works so slow for big ranges. for example x=0 , and y=3,000,000,000.

I'm sure that there is some relation that I can use to reduce the number of iteration and optimizing this code for speed. I searched but i could not find it out. Can any one help me with that please.

Thanks so much.


回答1:


This works: (e+1 - s) / d + (e%d < (s+d-1)%d). (It uses C semantics and integer arithmetic and assumes the start is non-negative. s is the start value, e is the end value [inclusive], and d is the divisor.)

Updated: A better solution is e/d - (s-1)/d. This was inspired by User448810. That requires s be positive; handling zero or negative s (or e) requires adjusting for the truncation toward zero (we would want toward negative infinity for this problem).

Update for negative values: The following works for any values of s and e in the range of their types, provided s <= e and 0 < d:

e = e <  0 ? (e+1)/d - 1 : e/d;
s = s <= 0 ? s/d - 1 : (s-1)/d;
return e-s;

Essentially, the first two statements are equivalent to e = e/d and s = (s-1)/d with the division modified to round toward -infinity instead of toward zero (so that -1/10 produces -1 rather than 0).




回答2:


(floor)(high/d) - (floor)(low/d) - (high%d==0)

Explanation:

There are a/d numbers divisible by d from 0 to a. (d!=0)

Therefore (floor)(high/d) - (floor)(low/d) will give numbers divisible in the range (low,high] (Note that low is excluded and high is included in this range)

Now to remove high from the range just subtract (high%d==0)

Use fmodf for floats.




回答3:


Only this implementation works for me (A, B in [0..2kkk]; K in [1..2kkk]):

function solution(A, B, K) {
    if(B < K) return A === 0 ? 1 : 0;
    if(A === B) return A % K === 0 ? 1 : 0;

    var pre = A === 0 ? 2 : 1;
    var min = A < K ? K : A + A % K;
    var max = B - B % K;

    return (max - min) / K + pre;
}



回答4:


Rather than iterating over each and every number, you could try

public int test(int floor, int ceil, int n) {
    int a = (floor / n) + 1;
    int counter = 0;
    while (a * n <= ceil) {
        counter++;
        a++;
    }
    return counter;
}

and only use multiples of the divisor. Now you're not doing repeated division (slow), you're doing repeated multiplication (faster).




回答5:


I'm pretty sure you can do this:

public static int numDivisible(int low, int high, int test) {
    return (high-low)/test;
}

There you go. A constant-time solution. Since you don't need to know exactly which numbers are divisible, you don't need to bother iterating through all of them.

EDIT: Change this to the following, as per @Chaser324.

public static float numDivisible(float low, float high, float test) {
    return Math.ceil((high-low)/test);
}

EDIT: A small typo ie., changed text to test




回答6:


You asked for a count of the number of integers between x and y (both x and y are included in the range) that are divisible by n. There is no need for any looping, and only two divisions are necessary to compute the answer. Let's consider a simple example: for the range 100 to 200, how many integers are divisible by 7?

Start at the low end of the range: 100 / 7 = 14 with a remainder of 2. Now the divisor 7 minus the remainer 2 is 5, so the smallest number on the range that is divisible by 7 is 100 + 5 = 105.

Now go to the high end of the range: 200 / 7 = 28 with a remainder of 4, so the largest number on the range that is divisible by 7 is 200 - 4 = 196.

Thus, the numbers on the range that are divisible by 7 are 105, 112, 119, 126, 133, 140, 147, 154, 161, 168, 175, 182, 189, and 196. There are 14 of them, which you can calculate in a couple of ways. Take the quotient at both ends and subtract them: 28 - 14 = 14. Or take the difference of the two endpoints, divide by the divisor, and add 1: 196 - 105 = 91, 91 / 7 = 13, 13 + 1 = 14. But be careful when one of the endpoints is divisble by the divisor; I'll leave it to you to work out the details, and also to write the program.




回答7:


Kindly provide comments on algorithm below: Suppose the range is [R1,R2] and number to be divided is n.

Find the smallest number starting from R1 divisible by n.Call it small.

Find the largest number starting from R2 divisible by n. Call it large.

Total numbers that are divisible= (large-small)/n + 1.

Worst case is still O(n) but might be efficient for large difference between R1 and R2.Hopefully I have covered all cases. Kindly suggest.

int numofDivisible(int R1, int R2, int n) {

int small = R1, large= R2;

if ((R1 > R2) || (n==0)) return 0;

if (R1 == R2) {
    if (R1 % n == 0) 
        return 1;
    else 
        return 0;
}

while(small <= R2){

     if(small % n == 0)
         break;

      ++small;
}

if (small > R2)
    return 0;


while (large > small) {

    if (large % n == 0)
       break;

    --large;
}

if (large == small)
   return 1;

return ((large-small)/n + 1);

}



回答8:


public static int solution(int low,int high, int n) {
    boolean h0=high%n==0;
    boolean l0=low%n==0;

    int k1=l0?low/n:(low+n-low%n)/n;
    int k2=h0?high/n:(high+n-high%n)/n;

    //                 |-----------|
    // ---------------k1----------k2---------------

    if(k2*n>high) k2--;

    return k2-k1+1;

}



回答9:


 public int myfunc(int low, int high, int test) {   
    int count = 0;
    if(low % test == 0)
       count++;
    count +=(high-low)/test;
    return count;
 }



回答10:


Well, I am not a university professor so I don't hold some amazing formula for you, but really as far as I know the only way to check over a list of numbers like that is to iterate over them, in the end you will have to evaluate the variable to check wether it is divisible, now there is a way to optimise your algorithm, sort the numbers first! This will initially be expensive, but any successive needs to check the numbers would be much faster,

I suggest looking at sorting algorithms, the one I would use would be bubble sort, which will come up on google quite a bit.

As for what you can do with the sorting, you could sort numbers into lists of of multiples, for instance 2 4 6 8 are all multiples of 2 so you could basically check the first in the list, and the rest would be instantly known to also be divisible

Keep in mind there may be a much more efficient way of doing this, just offering my 2 cents



来源:https://stackoverflow.com/questions/11805004/optimize-code-to-get-the-number-of-integers-within-given-range-that-are-divisibl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!