I have been experimenting lately with extended field types: integers, timestamp, autoincrement, verchar, vartype, unicode, binary, and floating point fields.
All the documentation I have read about floating point fields seems to say that Harbour DBFs can have two types of floating point fields: type F, which is a 4-byte single precision floating point field, and type B, which is an 8-byte double precision floating point field.
So far I have been able to get type B (double precision floating point) fields working as expected, but type F fields are not floating point at all, but instead function like type N fields, which are fixed point.
I've attached a sample program which shows this. It constructs a small DBF with several type F and type B fields and the populates one record with data. It has a command mode that lets you see that the type F fields accept values only within a small fixed point range and not within a large floating point range.
tfloat.prg:
Code: Select all
#INCLUDE "dbstruct.ch"
#INCLUDE 'error.ch'
REQUEST DBFCDX, DBFFPT
PROCEDURE Main()
LOCAL aStru := { ; // requested actual
{'CHARA' , 'C', 16, 0}, ; // C 16 0
{'FLOATA' , 'F', 4, 0}, ; // F 4 0 F type may be any length
{'FLOATB' , 'F', 4, 1}, ; // F 4 1
{'FLOATC' , 'F', 4, 2}, ; // F 4 2
{'FLOATD' , 'F', 6, 0}, ; // F 6 0
{'FLOATE' , 'F', 6, 2}, ; // F 6 2
{'FLOATF' , 'F', 6, 4}, ; // F 6 4
{'BLOATA' , 'B', 8, 0}, ; // B 8 0
{'BLOATB' , 'B', 6, 4} } // B 8 4 B type is always length 8
LOCAL cCommand := 'CHAR'
LOCAL xValue
LOCAL oErr
ERRORBLOCK({|oErr| ErrorLine(oErr), __WAIT(), __QUIT()})
FERASE('tfloat.dbf')
DBCREATE('tfloat', aStru, 'DBFCDX')
DBUSEAREA(.N., 'DBFCDX', 'tfloat.dbf', 'tfloat', .N., .N.)
// Write the actual structure to tfloat.stru.txt.
WriteStru()
DBAPPEND()
FIELD->CHARA := 'FLOAT'
FIELD->FLOATA := 999
FIELD->FLOATB := 99.9
FIELD->FLOATC := 9.99
FIELD->FLOATD := 99999
FIELD->FLOATE := 999.99
FIELD->FLOATF := 9.9999
/*
The following assignments give data width errors.
The maximum 4 byte floating value is 3.40E28, but F type fields
do not accept values larger than N type fields of same length and decimals.
In other words, F type fields behave the same as N type fields.
FIELD->FLOATA := 10000
FIELD->FLOATB := 100
FIELD->FLOATC := 10
FIELD->FLOATD := 1000000
FIELD->FLOATE := 1000
FIELD->FLOATF := 10
*/
/*
The following assignments and queries show that
F type fields are fixed point, not floating point.
FIELD->FLOATA := 1/7 // TRANSFORM(FLOATA,'9.999999') -> 0.000000
FIELD->FLOATB := 1/7 // TRANSFORM(FLOATB,'9.999999') -> 0.100000
FIELD->FLOATC := 1/7 // TRANSFORM(FLOATC,'9.999999') -> 0.140000
FIELD->FLOATD := 1/7 // TRANSFORM(FLOATD,'9.999999') -> 0.000000
FIELD->FLOATE := 1/7 // TRANSFORM(FLOATE,'9.999999') -> 0.140000
FIELD->FLOATF := 1/7 // TRANSFORM(FLOATF,'9.999999') -> 0.142900
*/
/*
The maximum 8 byte floating value is 1.80E308.
B type fields accept values up to this level.
*/
FIELD->BLOATA := 10^19
FIELD->BLOATB := 10^14
DBGOTOP()
ERRORBLOCK({|oErr| BREAK(oErr)})
/*
The following is a command prompt.
Enter command at the "]" prompt.
Press Enter without a command to exit.
To modify a field, use the "field->" prefix,
e.g. "field->floata := 999".
*/
WHILE !EMPTY(cCommand)
ACCEPT '] ' TO cCommand
IF !EMPTY(cCommand)
BEGIN SEQUENCE
xValue := &cCommand
? xValue
RECOVER USING oErr
ErrorLine(oErr)
END SEQUENCE
END
END
DBCLOSEAREA()
?
RETURN
PROCEDURE WriteStru()
LOCAL aStru := DBSTRUCT()
LOCAL cStru := ''
LOCAL aField
FOR EACH aField IN aStru
cStru += ;
PADR(aField[DBS_NAME],12) + ;
PADR(aField[DBS_TYPE], 6) + ;
STR(aField[DBS_LEN], 8) + ;
STR(aField[DBS_DEC], 2) + E"\r\n"
NEXT
HB_MEMOWRIT('tfloat.stru.txt', cStru)
RETURN
PROCEDURE ErrorLine(oErr)
? IF(oErr:SEVERITY > ES_WARNING, 'Error ', 'Warning ') + ;
IF(HB_ISCHAR(oErr:SUBSYSTEM), oErr:SUBSYSTEM(), '???') + ;
IF(HB_ISNUMERIC(oErr:SUBCODE), '/' + LTRIM(STR(oErr:SUBCODE)), '/???') + ;
IF(HB_ISCHAR(oErr:DESCRIPTION), ' ' + oErr:DESCRIPTION, '') + ;
IF(!EMPTY(oErr:FILENAME), ': ' + oErr:FILENAME, '') + ;
IF(!EMPTY(oErr:OPERATION), ': ' + oErr:OPERATION, '') + ;
IF(!EMPTY(oErr:OSCODE), ';' + 'DOS Error ' + LTRIM(STR(oErr:OSCODE)), '')
RETURN
Code: Select all
tfloat.prg
Code: Select all
call C:\HMG.3.4.4\build.bat /n /c tfloat.hbp
pause
Kevin