#Modulo returning incorrect remainder

26 messages · Page 1 of 1 (latest)

proper bough
#

I'm writing a code to return the prime factors of a number, and it's worked for smaller numbers just fine, but for some reason there is a large number that keeps returning 0 when I know for a fact that there is a remainder.

func primeFactors(n int64) []int64 {
    var factorSeq []int64

    x := 1 // ignore
    for i := 2.0; n > 0.0; {
        if checkPrime(i) {
            if math.Mod(float64(n), i) == 0.0 {
                fmt.Println("Factor", x, ":", i, "=", n/int64(i), "R", math.Mod(float64(n), i))
                factorSeq = append(factorSeq, int64(i))
                n = n / int64(i)
                x++ // ignore
            } else {
                i++
            }
        } else if int64(i) > n {
            break
        } else {
            i++
            //fmt.Println(i)
        }
    }

    fmt.Println("Prime Factors: ", factorSeq)
    return factorSeq
}```

Attached are my outputs:
#

It should move on to 3 after Factor 7, Factor 8 should have a remainder of 0.5. Where am I going wrong?

#

I believe that each of those remainders should be 0.0, 0.5 etc, but for some reason it's rounding. I don't have anything rounding out the remainder, it should just straight up do math.Mod(float64(n), i)

tulip escarp
#

Difficult to read the code when you're doing the maths and the printing on the same line.

proper bough
#

the next line is just to troubleshoot outputs. to see what it's doing.

tulip escarp
#

It's not very easy to check for equality against 0.0.

proper bough
#

What should I check for, then?

tulip escarp
#

Floats aren't precise so you must check if it's within a certain range.

#

An absolute 0.0is rare except for when you start out with zero.

proper bough
#

So, 0.05 would also return true for that?

tulip escarp
#

You would need to check if the absolute value of the delta between two floats is lower than your accepted precision.

proper bough
#

I'm thinking of another function that checks the delta of float x and math.Ceil(x) - would something like that work?

tulip escarp
#

All you need is math.Abs

#

And then check if it's less or equal to a certain precision.

#

When you want to compare against zero, you could do something like this:
if math.Mod(float64(n), i) <= 1e-9 {

#

But if you want to compare against something that's not zero, you would need to use subtraction and math.Abs

#

Like this math.Abs(x-y) <= p where xand y are your two floats and p is the precision.

#

If your numbers might be negative, you'd need to use math.Abs

#

This is required because of how floating point numbers work.

#

They are not exact.

#

You're not likely going to get a perfect 0.0when you do arithmetic operations with floats.

proper bough
#

Wait okay I think I’m getting it, give me a bit

swift parcel
#

In most cases in computing “modulo” is generally defined for non-negative integers. When checking for prime-ness you really care about exact values, and I would suggest you look into a large integer library if you’re interested in values bigger than would fit comfortably in an int64 (values more than square root of 2 to the power of 63… about 3 billion). Integer division typically discards anything after the decimal point, so if you are unable to use modulus, I would multiply back and compare the result. Be aware that large integer libraries are not going to be as efficient as operations within the CPU’s but width.

swift parcel
#

In golang math/big (an arbitrary precision large number package) is part of the standard library. I haven’t used it myself, but I expect it will meet your needs: https://pkg.go.dev/math/big