# GNU BC: “modulo” % with scale other than 0

If the scale is other than zero, calculations with %, such as 3%2 and 46%4, tend to output 0. How is the algorithm designed with the scale other than 0?

``````bc
scale=10
print 4%3   // output 0
``````
-
For those who just want something that works: `define mod(x,base){oldscale=scale; scale=0; result=x%base; scale=oldscale; return result }` – Hello World Oct 12 '14 at 12:16

The command manual says this about how BC calculates the modulo:

The result of the expression is the "remainder" and it is computed in the following way. To compute a%b, first a/b is computed to scale digits. That result is used to compute a - ( a/b ) * b to the scale of the maximum of scale+scale(b) and scale(a). If scale is set to zero and both expressions are integers this expression is the integer remainder function.

EDIT: I looked at the source code for GNU BC and found that the mod operator extends the division operator. In other words, the modulo is calculated as a by-product of the division. It relies on integer division to calculate the modulo. When `scale` is set, however integer division does not take place.

Try this in BC:

``````bc
scale = 0
print 5/2

scale = 5
print 5/2
``````

you should get:

``````2        << Integer Division
2.50000  << NOT integer division!
``````

Now let's plug in these figures the way BC does. The manual says it uses a-(a/b)*b to calculate. Let's plug in our two results, the one resulting from integer division and the one with a `scale` other than 0.

``````a - ( a/b ) * b
5 - ( 2   ) * 2  = 1  << CORRECT!
5 - ( 2.5 ) * 2  = 0  << VERY WRONG!
``````

Without integer division:

``````a - ( a/b ) * b == a - (  a  ) == 0
``````

This is why scale must be set to 0 for the modulo to work properly.
The issue seems to arise out of the design of BC and how it handles numbers with a 'scale'. In order for the modulo to work correctly we need integer division.

There are other much more advanced tools that are free and open source for this purpose, and I recommend you use them.

-
I am also getting the same results. – tj111 Aug 28 '09 at 17:25
Your scale is 0, not "other than zero". Please, set it with "scale=10", for example, and then try "3%2". – user3672 Aug 28 '09 at 17:54
thanks for the clarification. I'll update my answer. – jweede Aug 28 '09 at 18:10
when it says 'scale' with no parenthesis, it refers to the global variable 'scale'. – jweede Aug 31 '09 at 11:55
I'm not sure why it needs to be `scale+scale(b)` since the `scale` of a/b should generally be zero for it to give meaningful output. – jweede Sep 3 '09 at 13:19

user272970's answer is great. Here's a tweak to it:

``````define int(x) { auto oldscale; oldscale=scale; scale=0; x=x/1; scale=oldscale; return( x ); }
define fmod(x,y) { auto oldscale; oldscale=scale; scale=1000; x = x - y * int(x/y); scale=oldscale; return( x ); }
``````

This (using `auto oldscale`) makes `oldscale` local to the function. Without that, setting `oldscale` in `int()` from fmod() will overwrite the `oldscale` that is trying to be saved in `fmod()`, leaving `scale` set to 1000 instead of whatever you had before calling `fmod()`.

I added these functions to `~/.bcrc` and set the `BC_ENV_ARGS` environment variable to `~/.bcrc`. That will load these functions every time you run bc. So now I can just run `fmod(x,y)` any time I'm in bc without having to manually define those functions every time.

p.s. `scale` of 1000 might be overkill in most cases

-

I solved it this way:

# integer

define int(x) { oldscale=scale; scale=0; x=x/1; scale=oldscale; return( x ); }

# modulo

define mod(x,y) { oldscale=scale; scale=1000; x = x - y * int(x/y); scale=oldscale; return( x ); }

HTH

-