Ask Your Question
0

Sage - problem during dividing

asked 2021-04-21 18:15:20 +0200

Miroslaw gravatar image

updated 2021-04-21 21:49:02 +0200

I'm using https://sagecell.sagemath.org/ I tried divide by 2 some integers like:

test no 1:
integer to divide                                      : 1178491952578374405023980117478966721  
after divide by 2                                      :  589245976289187203169105266910167040
multiply by 2 to get integer before divide : 1178491952578374406338210533820334080

test no 2:
integer to divide                                      : 1061618174439266951056499776554456999
after divide by 2                                      : 530809087219633493358671479116398592
multiply by 2 to get integer before divide : 1061618174439266986717342958232797184

test no 3:
integer to divide                                      : 1272974170381429325805079139420165714
after divide by 2                                      : 636487085190714687068002546205327360
multiply by 2 to get integer before divide : 1272974170381429374136005092410654720

why result after divide is wrong??

If I change language from sage to python is even worst...

code:

    import random

def delete_0(value):
    report = False
    len_s=len(value)
    while report == False:
        if value[len_s-1] == "0":

            report = False
            #print("przed :",value)
            value=value[:-1]
            #print("po :",value)
            len_s=len(value)
        if value[len_s-1] != "0":
            report = True
        if len(value)==1:
            report = True
    return value        

def printStr(FloatNumber, Precision):
    return "%0.*f" % (Precision, FloatNumber)




def gen_value(liczba):
    d = liczba

    l =[]

    ile = len(str(d))
    w = printStr(d,ile)
    l = str(w).split(".") 
    w = l[1]
    r = delete_0(w)
    return l[0] +"."+r

#number to divide as random.randrange
number =  1272974170381429325805079139420165714 #random.randrange((2**119),2**120)

to_test = number
print("number to divide by 2 : ",number)

number =(number /2)  
print("i-th divide: ",i," # after divide : ",number)
print("i-th divide: ",i," # after divide : ",Reals(120)(number))
print("number as more precisied: ",gen_value(number))

print("Test : after multiply * 2 is equal? ",(float(number)+float(number) ) == to_test)
edit retag flag offensive close merge delete

Comments

Please display your test code. And also operating system, sage version, etc

FrédéricC gravatar imageFrédéricC ( 2021-04-21 20:51:45 +0200 )edit

2 Answers

Sort by » oldest newest most voted
1

answered 2021-04-21 22:16:09 +0200

updated 2021-04-21 22:17:27 +0200

Python's float does not have high precision, and when you do the division number/2 in Python, that's what you get. Try replacing number with Integer(number) to make sure you use Sage's arbitrary precision integers; once you've done that, then any divisions (for example) involving these integers will remain exact. Try to avoid converting to float either explicitly or implicitly. Here is an example illustrating some differences between Sage Integer and Python int: Sage

sage: type(4)                                                                                                            
<class 'sage.rings.integer.Integer'>
sage: 4/3                                                                                                                
4/3
sage: type(4/3)                                                                                                          
<class 'sage.rings.rational.Rational'>
sage: 3 * 4/3                                                                                                            
4

as compared to Python

>>> type(4)
<class 'int'>
>>> 4/3
1.3333333333333333
>>> type(4/3)
<class 'float'>
>>> 3 * 4/3
4.0

Also, you lose precision when you move from Sage numeric types to Python ones:

sage: a = 117849195257837440502398011747896672 
sage: a                                                                                                                  
117849195257837440502398011747896672
sage: int(float(a))                                                                                                      
117849195257837440633821053382033408
edit flag offensive delete link more

Comments

thank you:)

Miroslaw gravatar imageMiroslaw ( 2021-04-22 14:29:20 +0200 )edit
0

answered 2021-04-23 06:39:53 +0200

Emmanuel Charpentier gravatar image

Another way to understand your problem is to consider what is to divide an integer by another. In general, the result of dividing an integer $n$ by an integer $d$ is

  • a quotient $q$, and
  • a remainder $r$

such as :

  • $n=q\cdot d+r$ and
  • $0\leq r\le d$

Such an operation is implemented as the quo_rem method of Sage's integers. In your examples :

sage: a = 1178491952578374405023980117478966721
sage: a.quo_rem(2)
(589245976289187202511990058739483360, 1)
sage: b=1061618174439266951056499776554456999
sage: b.quo_rem(2)
(530809087219633475528249888277228499, 1)
sage: c=1272974170381429325805079139420165714
sage: c.quo_rem(2)
(636487085190714662902539569710082857, 0)

The quotient can also be obtained by the // (integer division) operator, and the remainder by the % (modulo) operator :

sage: a//2
589245976289187202511990058739483360
sage: a%2
1
sage: b//2
530809087219633475528249888277228499
sage: b%2
1
sage: c//2
636487085190714662902539569710082857
sage: c%2
0

Your tests can be expressed as :

sage: a-(a//2)*2
1
sage: b-(b//2)*2
1
sage: c-(c//2)*2
0

Compare with :

sage: a-(a/2)*2
0
sage: b-(b/2)*2
0
sage: c-(c/2)*2
0

where the expressions a/2, b/2 and c/2 are Rationals :

sage: (a/2).parent()
Rational Field
sage: (b/2).parent()
Rational Field
sage: (c/2).parent()
Rational Field

The latter can be converted (technically coerced) to an integer :

sage: ZZ(c/2)
636487085190714662902539569710082857
sage: ZZ(c/2).parent()
Integer Ring

whereas the first one cannot :

sage: ZZ(a/2)
## Stack trace : elided
TypeError: no conversion of this rational to integer

but can be rounded to an integer :

sage: round(a/2)
589245976289187202511990058739483361
sage: round(a/2).parent()
Integer Ring

It should also be noted that Integers and Rationals are exact, in the sense that their representation is finite ; this contrasts with reals or copmplexes, whose representation may be infinite, and thus represented in machine by approximations such as the so called "floating point" numbers (floats in Python, various representations in Sage)

sage: (3/2).parent()
Rational Field
sage: (3/2).parent().is_exact()
True
sage: (1.5).parent()
Real Field with 53 bits of precision
sage: (1.5).parent().is_exact()
False

Some operations have meaning only if they are done on exact quantities (integers, rationals or algebraic). For exemple, testing the equality of two quantities by bool(x==y) means that "$x$ and $y$ are identical" if and only if x and y are exact ; if x or y are, for example, Sage's Reals with n bits of precision, the same tests succeeds if $|x'-y'|<2^{-n}$, where $x'$ and $y'$ are $x$'s and $y$'s mantissæ, i. e. numbers such as :

  • $x'2^{e_1}=x$, with $e_1\in\mathbb{Z}$, and

  • $\frac{1}{2}\leq x' \leq 1$.

This was the case of your tests : since you worked with "large" numbers, whose mantissa needed more than 53 bits for an "exact" representation, their floating point representations lost the last digits :

sage: a
1178491952578374405023980117478966721
sage: round(RR(a))
1178491952578374406338210533820334080

(In fact, you would need $\lceil \log_2a\rceil=120$ bits of precision to be able to represent a exactly, the same for b and c).

Other representations, such as intervals or balls, emphasize other aspects of the same problem.

HTH,

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2021-04-21 18:15:20 +0200

Seen: 52 times

Last updated: Apr 23