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.
DOUBLE's fractional digits to ULONGINT ?
Re: DOUBLE's fractional digits to ULONGINT ?
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 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.
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:
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.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.
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 Function
Function 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 Function
function rndX overload(s1 as ulongint) as ulongint
static as ulongint u=18446744073709551615
return iif(s1=u,Get64Bit(),Get64Bit() mod (s1+1))
end function
function range overload(byref f as string,byref l as string) as string
return plus (RndX(minus(l,f)),f)
end function
function range overload(byref f as ulongint,byref l as ulongint) as ulongint
return RndX((l)-(f))+(f)
end function
dim as ulongint u=18446744073709551615
randomize
for n as long=1 to 20
print range(u-3,u)
next
print "===================="
for n as long=1 to 20
print range("184467440737095516150000000000","184467440737095516150000000003")
next
sleep
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
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
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!"
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.
.
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"?)
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.
.