Please Change The Source Code For "%"(modulo) Operator

There are lots of problems about taking remainders of number couples. With integers, there is no problem. But when it comes to floating-point numbers( I mean, float-float or float-int couples), shell returns a nonsense answer.There is an example below:

>>> 5.8%2
1.7999999999999998  #Correct Answer: 1.8
>>> 25.34%5
0.33999999999999986 #Correct Answer:0.34

I recommend you to check numbers before taking them into the process. I will try to explain the “checker code” draft which is in my mind:
(x%y)
*
-If both numbers are integers, code directly sends these to the main process.

return (x,y) #You can do anything which directly returns x and y.(I preferred to return them as a tuple.)

-If there is a float between these to variables(x and y), code firstly does this(to make sure that both numbers are float):

x=float(x)
y=float(y)

Then, our code must calculate the lengths of the fractional(after-dot) pieces. We will use these lengths to make integers.

lenFractx=len(str(x).split(sep=".")[1])
lenFracty=len(str(y).split(sep=".")[1])

After that, we must change our floats into integers. (Because modulo returns a correct respond, if both numbers are integers.) To change a float into an integer -we want to use the same characters(12,34->1234)- we must multiply it with 10^^length_of_the_fractional_part.There is an example below:
**
ourFloatNumber=34.45
fractionalPartLength=2
ourIntegerNumber=34.45 * 10**2 #and this is equivalent to 3445
**
But, we have two numbers. To save their ratio, we must multiply them with the same number. And this number will be equivalent to the biggest fractional part’s length. So, at this point, our code must do something like this:

if lenFractx>lenFracty:
    x*=10**lenFractx
    y*=10**lenFractx
    floatMultiplier=lenFractx
else:
    x*=10**lenFracty
    y*=10**lenFracty
    floatMultiplier=lenFracty

Right now, our variables are ready to go. But you mustn’t forget to divide the remainder by 10^^biggest_fractional_length. You may add a new parameter to your remainder function called floatMultiplier(which will also has default value of None). If this parameter is None, your code won’t do anything extra. If it has an integer value passed into it, then your remainder function will divide the result by 10**floatMultiplier and return it.
I bringed together all this stuff here(I suppose your modulo function is called remainder and requires only two args):

if ("." not in str(x) and "." not in str(y)):
    remainder(x,y)
else:
    x=float(x)
    y=float(y)
    lenFractx=len(str(x).split(sep=".")[1])
    lenFracty=len(str(y).split(sep=".")[1])
    if lenFractx>lenFracty:
        x*=10**lenFractx
        y*=10**lenFractx
        floatMultiplier=lenFractx
    else:
        x*=10**lenFracty
        y*=10**lenFracty
        floatMultiplier=lenFracty
    remainder(x,y,floatMultiplier)

Stuff about your remainder function:

def remainder(x,y,floatMultiplier=None):
    #bla bla
    #result=something
    if floatMultiplier==None:
        return result
    else:
        return result/(10**floatMultiplier)

If you can take this into account, I will be really happy.
Note:I am sorry if there are any mistakes about phrases or language usage. English is not my mother language.Thank you for reading this.
*

As far as floating point arithmetic goes these are correct results. The difference between the correct and the “nonsense” number is the 64-bit floating point number machine precision. You can test it yourself without the modulo operator.

In[1]: 3.8-2
Out[1]: 1.7999999999999998
In[2]: 5.34-5
Out[2]: 0.33999999999999986
2 Likes

There’s a nice explanation about this sort of thing here:

https://docs.python.org/3/tutorial/floatingpoint.html

There are also some nice answers on this stackoverflow post: language agnostic - Is floating point math broken? - Stack Overflow

1 Like

Okay, I feel like a st_p_d(Maybe I am😅). But don’t we have any ways to make calculations totally base 10? I know there are 2^^x bytes in a computer, but how does base10 calculators work?
Edit(Answer to myself):It’s possible for them to use extra functions. Maybe they are slicing those fractional numbers and using integer math.

Yes. Use the decimal module.

1 Like

Yes, you can do your calculations in base 10 by using the decimal module.

But there are good reasons why serious numeric calculations are still done in base 2 (binary):

  • speed

  • accuracy

Decimal (base 10) has the advantage that every number you can write exactly in decimal notation (like 0.1) can be expressed exactly (up to the limit in digits). Decimal is especially useful when you are working with quantities representing money.

But it has the disadvantage that it will be slower, and for many computations, the rounding errors may be larger.

1 Like

Thank you for your all explanations and answers. I see the point now. @storchaka, @steven.daprano _ilayn _weeneyde (seems like i can mention max. 2 people because i am a new user, so i couldn’t mention everyone)