For the primes you should make something that spits out all primes <= num/2, then check against that list. No need to check all numbers up to num (but you should check whether num itself is prime).
There are definitely quite a few tricks you can do to generate a list of primes. Even just naive changes can speed up the process quite a bit. First up, other than 2, all primes will be odd. That halves your search space right away. Then you can realize the same things holds for 3, so you can now step up 6 places per loop, and only check the things that are not multiples of 2 or 3. so you check in this pattern:
// pre-check against 2 and 3 and 5 factors here.
for(int i = 6; i<=num/2;i+=6)
{
// first loop of i checks against 0,1,2,3,4,5. second loop if i checks aganist 6,7,8,9,10,11 etc
// i+0, i+2, i+4 are invalid (even), as is i+3 (multiple of three)
// so for each loop, you need to check i+1 amd i+5 only
// so this halves the checks (num/2) then checks only 1/3 remaining values. Total speedup factor = 6
}
You could extend this to also including factors of 5 in the pattern, but then you're skipping 30 places at once so it would be a bit more messy, and there are diminishing returns since you're only ruling out additional factors of i+5, i+25 out of every 30. The other multiples of 5 were already covered by being divisible by 2 or 3. Hence, this particular speed up is only viable up to factors of 3.