## ZX Floating point to Decimal code in BASIC

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
David G
Posts: 44
Joined: Thu Jul 17, 2014 7:58 am

### ZX Floating point to Decimal code in BASIC

I wrote this 10 years ago, not sure how accurate it is. But it seems to work. Comments/corrections are welcomed.

David G

Code: Select all

``````Sub FloatToDec (ZxString\$, DecNumber#)
Dim FirstByte As Double
Dim ZxDigits As Double
Dim SecondByte As Double
Dim t As Double
Dim Xdigits As Double
Dim ZxSign As Double
Dim figure As Double

zero\$ = String\$(5, Chr\$(0))
If ZxString\$ = zero\$ Then DecNumber# = 0: Exit Sub

'get sign from second byte
SecondByte = Asc(Mid(ZxString\$, 2, 1))
ZxSign = SecondByte And 128

'Adjust second byte after getting sign
Mid(ZxString\$, 2, 1) = Chr\$(SecondByte Or 128)

'drop trailing bytes that equal 0
'result in x\$
For f = 5 To 2 Step -1
If Asc(Mid(ZxString\$, f, 1)) Then
Exit For
End If
Next f
x\$ = Mid(ZxString\$, 2, f - 1)

'get # of binary digits needed from first byte
FirstByte = Asc(Mid(ZxString\$, 1, 1))
ZxDigits = FirstByte - 128

'drop trailing bits that equal 0
DecNumber# = Asc(Right(x\$, 1))
For f = 8 To 1 Step -1
If DecNumber# And 1 Then Exit For
Let DecNumber# = DecNumber# / 2
Next f
'f = number of significant bits

'get # of binary digits in base number
Xdigits = (Len(x\$) - 1) * 8 + f

'convert string to base number
t = 0   'counter for powers of figure (256)
figure = 2 ^ f
For f = (Len(x\$) - 1) To 1 Step -1
DecNumber# = DecNumber# + Asc(Mid(x\$, f, 1)) * figure * (256 ^ t)
t = t + 1
Next f

'based on exponent, modify number to correct number
'of binary digits
Let DecNumber# = DecNumber# * 2 ^ (ZxDigits - Xdigits)
If ZxSign Then Let DecNumber# = -DecNumber#
End Sub``````
Last edited by David G on Sun Jul 27, 2014 5:50 am, edited 1 time in total.

XavSnap
Posts: 689
Joined: Sat May 10, 2008 4:23 pm

### Re: ZX Floating point to Decimal code in BASIC

Hi,
Thanks David.

In VB81 Xur, the revers function (Decimal to ZXfp), seem to be bugged using "1.5", "1,2" values !
Can your have a look to this code : (Vb81 XuR/ZxToken:ModZXUtil.bas)
(I had to type VAL('"1.2") to get the right value!)

Code: Select all

``````
' ZX81 floating point number.
Type Zx81_Long
Exp As Integer ' - Exponent
man As String ' - Mantissa
End Type

Function dbl2zx81(Num As Single) As Zx81_Long
'On Error Resume Next

' * Converts a double to an inline-basic-style ZX81 floating point number.
' *
' * IN:      num  - Number to convert (dbl)
' * OUT:     &exp - Exponent (integer)
' * OUT:     &man - Mantissa (char)
' *

Dim IntNum As Double
Dim tmpint1 As Double
Dim tmpint2 As Double

Dim TmpVal As String
Dim Expon As Double

'    /* Special case for zero */
If Num = 0 Then
dbl2zx81.Exp = 0#
dbl2zx81.man = 0#
Exit Function
End If

'    /* If negative work with the absolute value */
If Num < 0 Then Num = -Num

dbl2zx81.Exp = Int(Log(Num) / Log(2))

If dbl2zx81.Exp < -129 Or dbl2zx81.Exp > 126 Then Exit Function

IntNum = ((Num / (2# ^ (dbl2zx81.Exp + Expon#))) * 2147483648#)

' 65536=&h10000
' 32767=&h7FFF

tmpint2 = IntNum - (Fix(IntNum / 65536#) * 65536#) - 28
tmpint1 = (IntNum / 65536#) And 32767#

If tmpint2 < 0 Then tmpint2 = 0

TmpVal = Hex16(UnsignedToLong(tmpint1)) & Hex16(UnsignedToLong(tmpint2))

dbl2zx81.man = TmpVal
dbl2zx81.Exp = dbl2zx81.Exp + 129#
Exit Function

Dbl_ERR:
Disp_Err 11, Str(Num)
End Function``````

olofsen
Posts: 167
Joined: Wed Jan 08, 2014 12:29 pm

### Re: ZX Floating point to Decimal code in BASIC

The "28" should perhaps be "128" to clear the sign bit for positive numbers?

Code: Select all

``````tmpint2 = IntNum - (Fix(IntNum / 65536#) * 65536#) - 128
``````

XavSnap
Posts: 689
Joined: Sat May 10, 2008 4:23 pm

### Re: ZX Floating point to Decimal code in BASIC

tmpint2 = IntNum - (Fix(IntNum / 65536#) * 65536#) - 28
tmpint2 = IntNum - (Fix(IntNum / 65536#) * 65536#) - 128

True, somethings wrong...
I don't know if i's due to a sign remover, or a "FIX" leek how had to correct the value using the "28" value !
In Zxfp, there isn't any sign, and all values are positive.
May be the VB integer leek, how use his own sign tag !
If the FIX value is translated in Integer, we lost 1 bit in the "FIX" return value...

olofsen
Posts: 167
Joined: Wed Jan 08, 2014 12:29 pm

### Re: ZX Floating point to Decimal code in BASIC

May be we can compare intermediate results: for num=12345, intnum=3236167680, tmpint1=0 and tmpint2=49380 or 0xc0e4 but it should be 0x40e4?

David G
Posts: 44
Joined: Thu Jul 17, 2014 7:58 am

### Re: ZX Floating point to Decimal code in BASIC

For comparison, here is the same BASIC routine converted to C++

known issues:
* since it doesn't calculate the FP conversion in the exact same way as ZX81 Basic, it rounds differently.
* I haven't tested or implemented E+00 notation for extremely large or extremely small numbers

Code: Select all

``````#include <math.h> // or <tgmath.h>

double FloatToDec(BYTE* ZxFP)
{   // input is the 5 bytes that comprise the floating point number
BYTE x[6];
double DecNumber = 0;
int f;
int t;
BYTE Xdigits;
int ZxDigits;
BOOL ZxSign;
double figure;

if(memcmp(ZxFP,"\000\000\000\000\000",5) == 0)
{
return 0;
}

//'get sign from second byte
ZxSign = ZxFP[1] & 128;

//'Adjust second byte after getting sign
BYTE dd = ZxFP[1];
ZxFP[1] = dd | 128;

//drop trailing BYTES that equal 0
//'result in x\$
for( f = 4; f >= 1; f--)
{
if(ZxFP[f] != 0)
break;
}
int len_x = f;
memcpy(x,ZxFP+1, len_x); //x[len_x]=0;

//'get # of binary digits needed from first byte
BYTE FirstByte =ZxFP[0];
ZxDigits = FirstByte - 128;

// drop trailing BITS that equal 0
BYTE bb = x[len_x - 1];
for(f = 8; f >= 1 ; f--)
{
if(bb & 1)
break;
bb = bb >> 1;
}
DecNumber = bb;
//f now contains the number of significant bits

//'get # of binary digits in base number
Xdigits = ((unsigned char)len_x - 1) * 8 + (unsigned char)f;

//'convert string to base number
t = 0; //   'counter for powers of figure (256)
figure = pow((double)2, f);
for(f = len_x - 1; f >= 1; f--)
{
DecNumber = DecNumber + x[f-1] * figure * pow((double)256,t);
t = t + 1;
}
//'based on exponent, modify number to correct number
//'of digits
DecNumber = DecNumber * pow((double)2,ZxDigits - Xdigits);
if (ZxSign)
DecNumber = -DecNumber;
return DecNumber;
}``````
For display, I use sprintf "%f", and truncate any '0' characters after the decimal point ('.')
Last edited by David G on Sun Jul 27, 2014 6:31 am, edited 1 time in total.

David G
Posts: 44
Joined: Thu Jul 17, 2014 7:58 am

### Re: ZX Floating point to Decimal code in BASIC

For ZX81 floating point, the sign is in the 2nd value byte as shown in the original "ZX81 BASIC Programming" book.

Chapter 27 - Organization of memory
Attachments
Chapter 27, figure 3 (variable memory diagram)
fig27_3.jpg (11.51 KiB) Viewed 4078 times

David G
Posts: 44
Joined: Thu Jul 17, 2014 7:58 am

### Re: ZX Floating point to Decimal code in BASIC

In VB81 Xur, the revers function (Decimal to ZXfp), seem to be bugged using "1.5", "1,2" values !
Can your have a look to this code : (Vb81 XuR/ZxToken:ModZXUtil.bas)
(I had to type VAL('"1.2") to get the right value!)
It appears to work correctly. I ran the posted code in Visual Basic and a sample number was correctly converted.

I downloaded ModZXUtil.bas from http://zx81.vb81.free.fr/download/VB81_RES.zip, however if does not appear have the function "Decimal to ZXfp" (dbl2zx81) in it. In the code above I don't see "1.5" or "1,2".

PokeMon
Posts: 2225
Joined: Sat Sep 17, 2011 6:48 pm

### Re: ZX Floating point to Decimal code in BASIC

For calculating/converting floating points in programs, this is a good source:

http://www.users.waitrose.com/~thunor/m ... ter17.html

XavSnap
Posts: 689
Joined: Sat May 10, 2008 4:23 pm

### Re: ZX Floating point to Decimal code in BASIC

Hi all,

I tried to use the David Gonzales's codes in an update of SnaList (from Chris Cowley) on Spectrum Tap/TZX.

A new C++ routine on the Floating Point conversion from _SAM_ & Hlide: (Fr lang)
http://forum.system-cfg.com/viewtopic.p ... b0e23879dd

Code: Select all

``````//*******************************************************************
// Spectrum/ZX81 Floating point decoder From _SAM_ et hlide
//*******************************************************************
//IN: 5 Bytes : 1 EXP + 4 Mantissa (sign on the secound byte)
//OUT: DOUBLE
double decode(unsigned char fp[5]) {
double mantisse;

if(fp[0]==0) {
double t = fp[1]*65536 + fp[3]*256 + fp[2];
if(fp[1]&128) t -= 256*65536;
return t;
}

mantisse = (((fp[4]/256.0 + fp[3])/256.0 + fp[2])/256.0 + fp[1])/128.0;
if(mantisse < 1) mantisse += 1;  // nombre positif
else mantisse = -mantisse; // nombre negatif

return mantisse*pow(2, fp[0]-129);
}``````
[EDITED 2018-04-24]
Last edited by XavSnap on Tue Apr 24, 2018 5:54 pm, edited 1 time in total.