## DOUBLE's fractional digits to ULONGINT ?

General FreeBASIC programming questions.
cbruce
Posts: 136
Joined: Sep 12, 2007 19:13
Location: Dallas, Texas

### Re: DOUBLE's fractional digits to ULONGINT ?

Yep, Integer... thanks... but paul doe already straightened me out on that a few posts above.

I was just pointing out the error in the direction of the on-going conversation.
jj2007
Posts: 1818
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

### Re: DOUBLE's fractional digits to ULONGINT ?

cbruce wrote:The constant must be the correct value in relation to the length of the number of digits in the double's fractional component - or else the resulting ulongint will either have too few or too many digits.
Apparently you didn't read my post of Apr 09, 2018 2:16 above: There is no "correct" value. What you get when converting a double to a string is always "incorrect". A double allows roughly 16 correct digits, a REAL10 about 19 (you can go beyond that with a bignum library, of course).
cbruce
Posts: 136
Joined: Sep 12, 2007 19:13
Location: Dallas, Texas

### Re: DOUBLE's fractional digits to ULONGINT ?

Apologies jj2007... my comment about "errors" was not in relation to the purity of mathematics - but in relation to the purpose I was going to put the results to. As my example from a couple of posts ago explained:
Example:
If I was looking for a max range double of 0.6804801726248115 - and I ended up with a max range ulongint of 680480172624811530 to use in the random range calculation - I could easily end up with a random ulongint, that when translated back to a double, would be a larger value than the max double requested, etc.

The *error* in question would cause magnitudes of difference when using a set of a DOUBLE's fractional digits in a ULONGINT representation. That was why the original purpose was to find a way (other than with strings) to get an *exact* representation of those digits - so that the magnitude would scale, correctly, along with the representation.
dodicat
Posts: 6761
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: DOUBLE's fractional digits to ULONGINT ?

Here are two random rangers for ulongint and above.

Code: Select all

` Function plus(Byval num1 As String,Byval num2 As String) As String    Static As Const Ubyte AddQMod(0 To 19)={48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57}    Static As Const Ubyte AddBool(0 To 19)={0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1}    Var n_=0    Dim As Ubyte addup=Any,addcarry    #macro finish()    Return Ltrim(answer,"0")    #endmacro    If Len(num2)>Len(num1) Then  Swap num2,num1    Var diff=Len(num1)-Len(num2)    Var answer="0"+num1    For n_=Len(num1)-1 To diff Step -1         addup=num2[n_-diff]+num1[n_]-96        answer[n_+1]=ADDQmod(addup+addcarry)        addcarry=ADDbool(addup+addcarry)    Next n_     If addcarry=0 Then         finish()    End If    If n_=-1 Then         answer[0]=addcarry+48        finish()    End If    For n_=n_ To 0 Step -1         addup=num1[n_]-48        answer[n_+1]=ADDQmod(addup+addcarry)        addcarry=ADDbool(addup+addcarry)        If addcarry=0 Then Exit For    Next n_    answer[0]=addcarry+48    finish()End FunctionFunction minus(byval num1 As String,byval num2 As String) As String    Static As Const Ubyte subqmod(19)={48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57}    Static As Const Ubyte subbool(19)={1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}    Dim As Integer bigger              Dim sign As String * 1    Var lenf=Len(NUM1)    Var lens=Len(NUM2)    #macro finishup()    answer=Ltrim(answer,"0")    If answer="" Then Return "0"    Return sign+answer    #endmacro    #macro compare()    If Lens>lenf Then bigger= -1:Goto fin    If Lens<lenf Then bigger =0:Goto fin    If NUM2>NUM1 Then         bigger=-1    Else        bigger= 0    End If    fin:    #endmacro        compare()    If bigger Then         sign="-"        Swap NUM2,NUM1        Swap lens,lenf    End If    Var diff=lenf-lens    Dim As String answer=NUM1    Dim As Integer n    Dim As Ubyte takeaway,subtractcarry    subtractcarry=0    For n=lenf-1 To diff Step -1         takeaway= num1[n]-num2[n-diff]+10-subtractcarry        answer[n]=Subqmod(takeaway)        subtractcarry=Subbool(takeaway)    Next n         If subtractcarry=0 Then:finishup():End If    If n=-1 Then:finishup():End If    For n=n To 0 Step -1         takeaway= num1[n]-38-subtractcarry         answer[n]=Subqmod(takeaway)        subtractcarry=Subbool(takeaway)        If subtractcarry=0 Then Exit For    Next n    finishup()End Function  Function Get64Bit() As UlongInt  Return (Cast( Ulongint, Rnd*(2^32) ) Shl 32) Or Cast( Ulongint, Rnd*(2^32) )   End Function   Function rndX overload(s1 As String) As String    #macro GetNumber    #define range(f,l) Int(Rnd*((l+1)-(f))+(f))    s[0]=range(48,s1[0])    For n As Long = 1 To L-1        s[n]=range(48,57)    Next    #endmacro    #macro compare(n1,n2,ans)    Scope        Var lenn1=Len(n1),lenn2=Len(n2)        If lenn1 > lenn2 Then ans=-1:Goto lbl        If lenn1 < lenn2 Then ans=0:Goto lbl        If n1 > n2 Then ans = -1  Else ans= 0        lbl:    End Scope    #endmacro    Dim As Long L=Len(s1),ans=1    Dim As String s=String(L,0)    While ans        GetNumber        compare(s,s1,ans)    Wend    Return Ltrim(s,"0")End Functionfunction rndX overload(s1 as ulongint) as ulongint    static as ulongint u=18446744073709551615    return iif(s1=u,Get64Bit(),Get64Bit() mod (s1+1))end functionfunction range overload(byref f as string,byref l as string) as string    return  plus (RndX(minus(l,f)),f)end functionfunction range overload(byref f as ulongint,byref l as ulongint) as ulongint   return RndX((l)-(f))+(f)end functiondim as ulongint u=18446744073709551615randomizefor n as long=1 to 20    print range(u-3,u)nextprint "===================="for n as long=1 to 20    print range("184467440737095516150000000000","184467440737095516150000000003")nextsleep `
coderJeff
Posts: 3393
Joined: Nov 04, 2005 14:23
Contact:

### Re: DOUBLE's fractional digits to ULONGINT ?

cbruce, glad you got an answer. paul doe's post is a solid algo. I have been interested in floating point lately and I tried really hard to break the linear interpolation. Best I could do is that the value returned might be a *tiny* bit greater than minimum value if RND() returns zero, and due to conversion error (expected) from decimal constant to floating point representation. As jj2007 points out, floating point is never exact, and when converting between floating point and decimal there are typically errors (expected) in the conversion. So as long as you only use the floating point representation, you should not have any trouble with paul doe's code.

Nit-pick: the notion that floating point fraction could be represented EXACTLY in a ulongint is incorrect: a DOUBLE is an approximation of a decimal number. I don't understand the trip to ulongint in the OP. An analogy for converting floating point to decimal is kind of like converting between number of weeks and number of days; exact sometimes, but mostly not.

if you want to to see exact decimal conversions, I posted at Exact double to decimal conversion
cbruce
Posts: 136
Joined: Sep 12, 2007 19:13
Location: Dallas, Texas

### Re: DOUBLE's fractional digits to ULONGINT ?

'
FYI coderJeff... SWEET converter code !!!
.
Everyone take note... I DON'T need an answer any more! [grin]

I'm just responding to coderJeff here because he is unclear about what (or why) I was asking in the OP.

Note: Most of the verbiage that I used was about "translating" digits between DOUBLEs and ULONGINTs... not "converting" the types. I was just hoping there was a mathy way to accomplish that... as opposed to using strings - (performance issue).

Clarification:

If you have an RNG that works on integers, not doubles (and I do)... and you are a math dummy (and I am).... and people want you to return double values in a specific range (the nerve of some people)... ... ...

Then you might think, "Hey! If I had two integers that were pictures (digit for digit) of the two range double's decimal digits... then I could do a range on those integer values and turn the digits of the resulting random integer back into a picture of a double's digits to return to the silly person that needed a double!"

Code: Select all

`0.2897989883, 0.478236622224      'Want a double in this range...'Str() those and grab just their fractional digits...'CULngInt() those strings...2897989883, 478236622224          'Generate a ulongint in this range... (easy with my integer rng)...349348734897                      'generated RND...0.349348734897 <== CDbl("0." + Str(349348734897))And you end up with a double that is guaranteed to be in the requested range!!!But I didn't want all the STRING stuff... (can anyone say "performance issue"?)`

Yes!... It turns out there are (MUCH) simpler ways to get there... I know that now. But I'm just a coder... so I took a hammer to the math that got in my way! [BIG grin]

I'm focused on the PCG RNG, that is based on an LCG, which calculates with and returns integers. The main reason is that an integer LCG allows for the capability of advancing|jumping|skipping back and forth in the sequence stream... a capability that can be extremely useful in a lot of mathy scenarios... and a capability that is not available in an RNG that actually works with floats - (as opposed to using an LCG integer RNG with the output converted to floats).

I hope that makes the OP clearer.

And a HUGE thanks to everyone that responded... perhaps there is a piece of math brain in my head that will kick in before I die.
.