Floating point fields

Harbour, MingW related news.

Moderator: Rathinagiri

Post Reply
User avatar
kcarmody
Posts: 152
Joined: Tue Oct 07, 2014 11:13 am
Contact:

Floating point fields

Post by kcarmody »

Hello again everyone,

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
tfloat.hbp:

Code: Select all

tfloat.prg
Build.bat:

Code: Select all

call C:\HMG.3.4.4\build.bat /n /c tfloat.hbp
pause
I got the impression that extended field types are FoxPro compatible. Does anyone have experience using type F fields in FoxPro? Did you find them to be fixed point or floating point? If they were floating point in FoxPro, then we may have a Harbour incompatibility.

Kevin
User avatar
esgici
Posts: 4543
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Contact:

Re: Floating point fields

Post by esgici »

Viva INTERNATIONAL HMG :D
User avatar
kcarmody
Posts: 152
Joined: Tue Oct 07, 2014 11:13 am
Contact:

Re: Floating point fields

Post by kcarmody »

Thank you, Esgici, for that link. The table at the top of that page is a fairly good outline of what I have found out so far. There are many more details I have found by experimentation that are not mentioned in this table or any other resource I have found.

I think I now have an answer to my question about type F fields. I was confused because several sources say that type F is a "float" field, without any further details. But halfway down a page on a FoxPro forum, http://fox.wikis.com/wc.dll?Wiki~VFPDataTypes, we have this:
Numeric and Float data types are identical. The only difference is the spelling of the name of the data type. The Float type was introduced to Fox for compatibility to dBase IV many yearas ago. IN VFP the float type is no different than the numeric type.
Hmmm, I see it is stored in plain ascii text, just like a Numeric (like you said). So it isn't a floating point at all.
No it is not floating point. It was added so that Fox would not choke on the Float type in a DBF created with dBASE IV. dBASE IV's Float is a floating point number, but Fox's is not.
Kevin
Post Reply