A question about double

General FreeBASIC programming questions.
Post Reply
hhr
Posts: 211
Joined: Nov 29, 2019 10:41

A question about double

Post by hhr »

Code: Select all

dim as double i,a,m=10.0123
i=10

a=m
print i*a-fix(i*a)
print frac(i*a)

a=i*m
print a-fix(a)
print frac(a)

sleep
With this example I get the following output.
An examination of the double number showed that 76 is correct in the end.
How can I understand this?

Code: Select all

gas32:
 0.1229999999999976
 0.1229999999999976
 0.1229999999999905
 0.1229999999999905

gcc32:
 0.1229999999999976
 0.1229999999999905
 0.1229999999999905
 0.1229999999999905

gcc64:
 0.1229999999999905
 0.1229999999999905
 0.1229999999999905
 0.1229999999999905

gas64:
 0.1229999999999905
 0.1229999999999905
 0.1229999999999905
 0.1229999999999905
hhr
Posts: 211
Joined: Nov 29, 2019 10:41

Re: A question about double

Post by hhr »

Dim As Double a

gas32:
The internal representation of a = 10.0123 represents the decimal number
+10.012299999999999755573298898525536060333251953125

The internal representation of a = 10.0123 * 10 represents the decimal number
+100.12299999999999045030563138425350189208984375

The internal representation of a = 100.123 represents the decimal number
+100.1230000000000046611603465862572193145751953125

gcc32:
The internal representation of a = 10.0123 represents the decimal number
+10.012299999999999755573298898525536060333251953125

The internal representation of a = 10.0123 * 10 represents the decimal number
+100.12299999999999045030563138425350189208984375

The internal representation of a = 100.123 represents the decimal number
+100.1230000000000046611603465862572193145751953125

So I should not say that the number with 76 at the end is correct.
hhr
Posts: 211
Joined: Nov 29, 2019 10:41

Re: A question about double

Post by hhr »

This is a preliminary example. I still have to check and test it.

Code: Select all

'#cmdline "-gen gcc -exx"

Function BigDiv1 (Byref a As String, Byref b As Ubyte) As String
   'Divides two positive numbers a\b; 1 <= b <= 9
   'ASCII: 48-0;49-1;50-2;51-3;52-4;53-5;54-6;55-7;56-8;57-9
   
   Dim As String q 'Quotient
   Dim As Ubyte dq, r 'r: Remainder
   Dim As Uinteger i, lena = Len(a)
   
   r = a[0] - 48
   
   If lena = 1 Then
      dq = r \ b
      q = Chr(dq + 48)
   Else
      For i = 0 To lena - 2
         dq = r \ b
         q = q & Chr(dq + 48)
         r = 10 * (r - dq * b) + a[i + 1] - 48
      Next i
      dq = r \ b
      q = q & Chr(dq + 48)
   End If
   
   'r=r-dq*b 'The remainder is not needed here.
   
   'This must not be used because decimal places are calculated here:
   'q = Ltrim(q,"0")
   'If q = "" Then q = "0"
   
   Function=q
End Function

Function BigAdd (Byref a As String, Byref b As String) As String
   'Adds two positive numbers
   'ASCII: 48-0;49-1;50-2;51-3;52-4;53-5;54-6;55-7;56-8;57-9
   
   Dim As Ubyte s,carry
   Dim As Integer lensum,lenmin,i
   Dim As String sum,summand
   
   If Len(a) < Len(b) Then
      sum = b
      summand = a
   Else
      sum = a
      summand = b
   End If
   
   lensum = Len(sum)
   lenmin = Len(summand)
   
   For i = 1 To lenmin
      s = sum[lensum - i] + summand[lenmin - i] - 96 + carry
      
      If s >= 10 Then
         sum[lensum - i] = s + 38
         carry = 1
      Else
         sum[lensum - i] = s + 48
         carry = 0
      End If
   Next i
   
   Do While carry And (lensum - i) >= 0
      s=sum[lensum - i] - 48 + carry
      
      If s >= 10 Then
         sum[lensum - i] = s + 38
         carry = 1
      Else
         sum[lensum - i] = s + 48
         carry = 0
      End If
      i = i + 1
   Loop
   
   If carry Then sum = "1" & sum
   
   Function=sum
End Function

Function BinaryToDecimal(number As Double) As String
   
   Union DoubleAndUlongint
      d As Double
      i As Ulongint
   End Union
   
   Dim As DoubleAndUlongint n
   Dim As Ulongint fraction,significand,pd,d 'Predecimal, Decimal
   Dim As Longint sign,exponent
   Dim As String s,s2,sres
   
   n.d = number
   
   Print Bin(n.i,64);" Number"
   
   sign = n.i Shr 63
   Print sign;" Sign"
   
   exponent = Cast(Longint,(n.i Shl 1) Shr 53) - 1023
   Print exponent;" Exponent (base 2)"
   
   If exponent = -1023 Then
      Return Iif(sign,"-0","+0")
   Else
      fraction = ((n.i Shl 12) Shr 12)
      significand = Bitset(fraction,52) 'Restore the 1
      Print Bin(fraction,64);" Fraction"
      Print Bin(significand,64);" Significand"
      
      If exponent >= 0 Then
         pd = significand Shr (52 - exponent)
         d = significand Xor (pd Shl (52 - exponent))
         s = Bin(d,52 - exponent)
         s2 = "5" & String(Len(s) - 1,"0")
      End If
      
      If exponent < 0 Then
         s = Bin(significand,53)
         s = String(Abs(exponent) - 1,"0") & s
         s2 = "5" & String(Len(s),"0")
      End If
      
      For i As Long = 0 To Len(s) - 1
         If s[i] = 49 Then sres = BigAdd(sres,s2)
         s2 = BigDiv1(s2,2)
      Next
   End If
   
   Function = Iif(sign,"-","+") & Str(pd) & "." & sres
   
End Function

Print "s" & " exponent  " & " mantissa" & space(44) & "s: sign"
Print "1" & String(11,"0") & String(52,"1");" Example" 
Print String(64,"-")

Dim As Double a
a = -10.0123
Print BinaryToDecimal(a);" Decimal"
Print a

Sleep
deltarho[1859]
Posts: 4313
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: A question about double

Post by deltarho[1859] »

Hi hhr

There is an issue using the FPU in 32 bit mode. Having said that, gcc 32 bit is OK on my machine.

I use '-fpmode fast -fpu sse' or '-fpu sse' for both 32 bit and 64 bit. Issue solved.

Turn on private messaging!
Post Reply