Short Single?

General FreeBASIC programming questions.
BasicJedi
Posts: 13
Joined: Mar 21, 2021 13:38

Short Single?

Post by BasicJedi »

Hello.I know, that compared to QBasic, FreeBasic has more datatypes.
For example: old QB 16bit Integer is now 32bit Integer, and 16bit Integer is Short or Integer<16>. There is also long and byte. And UInteger,Ushort etc...
But what about Single/Double? Single is 32bit and Double is 64.

Single allow 6 decimal digits while Double allow 15.

Is it possible to have Single/Double as 16bits data type?
And something like USingle and UDouble, becouse sometimes I need variable that use for example just numbers from 0.0 to 10.0 or from 0 to 1 with one or two digits.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Short Single?

Post by deltarho[1859] »

jevans4949
Posts: 1186
Joined: May 08, 2006 21:58
Location: Crewe, England

Re: Short Single?

Post by jevans4949 »

It's important to understand that a Single / Double is not held in decimal, but as a binary fraction, and one byte is taken by one bit for the sign and 7 bits for the power of 2 by which the fraction is to be raised. A single can hold a whole number up to a bit over 16 million decimal. Note also that any figures after the deimal point will be converted to a binary fraction, i.e. 1/2+1/4+1/8 etc, so 1/10, because it involves a power of 5 will be an approximation. a Double has an extra 32 bits of precision (significant figures), but the same rule applies.

I did once work at a company which had devised a 16-bit floating point number, to store figures from published company accounts, which are already approximations. That was in the days when disk storage was expensive.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Short Single?

Post by MrSwiss »

There are so called: Half-Floats (16bit) but not in FreeBASIC (not a basic data-type).

Unsigned Floats (of any size) whould break their 'design' which is 'IEEE 754 Standard'.
Currently published last time in 2020. See details: Wikipedia > IEEE 754
Last edited by MrSwiss on Sep 10, 2021 17:39, edited 1 time in total.
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Short Single?

Post by marcov »

Keep in mind that a signed 16-bit integer only has slightly more than 4 digits precision. Start taking bits off for a floating point exponent, and you quickly end up with no precision

Half floats are mainly used for AI interference matrices, where it is more magnitude (one/two digits+exponent). Only fairly new GPUs (not CPUs) support them as it is a fairly new type.
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: Short Single?

Post by angros47 »

In old QBasic integers were 16 bit; in FreeBasic, they are usually either 32 or 64 bits (depending on the architecture), but in "lang qb" they are 16 bit long, for compatibility (so, if a file has been created with a Quick Basic program, and that program is recompiled with FreeBasic, it can still read the same file)

Regarding floating point numbers, even old QBASIC already used 32 bit or 64 bit values, so there is no real reason to support 16 bit formats.

Actually, for floating point numbers, there were more formats in the past than today: in fact, in 16 bit era, most computers didn't support floating point numbers in hardware (to do that, you needed an external math coprocessor). For that reason, floating point numbers required softare routines to process them, and they could be stored in any format: one widely used format was the MBF (Microsoft Binary Format, used in GW Basic); the IEEE 754 was only one of the possible formats.
With more modern processors, the math coprocessor was integrated in the main CPU, and was called FPU (Floating Point Unit): since it used the IEEE 754 format, all other formats were abandoned, being unable to take advantage of the hardware. Even Microsoft Basic had to switch to the new format (old Quick Basic still provided the /MBF option to be able to read floating point numbers stored in the obsolete MBF format)

If you need a floating point number that uses only 16 bytes (or even only 8 bytes) it could be done using an user defined data type (class). But precision would be too low to be useful in most situations
BasicJedi
Posts: 13
Joined: Mar 21, 2021 13:38

Re: Short Single?

Post by BasicJedi »

Thanks for info. Good to know.
Few years ago I was programming little game in QBasic. And most problematic was floats numbers. Even Single was sometimes too precise :-)
For example when printing they are too long, ( always need to round it or use PRINT USING)
So I was avoided using Single/Double and hold data in integers
then print x/1000

But for basic tasks like simple games numbers like 0.005 (1/200) is enough. No need to use something like 0.005025125628140704 (1/199)
jevans4949
Posts: 1186
Joined: May 08, 2006 21:58
Location: Crewe, England

Re: Short Single?

Post by jevans4949 »

Another option worth considering is holding data in integers, but representing thousandths of whatever the variale is supposed to be. If you need to display these variables, write your own editing routine to place the decimal point and any leading zeros.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Short Single?

Post by jj2007 »

jevans4949 wrote:Another option worth considering is holding data in integers

Code: Select all

function GetHalf naked cdecl(byval s as short) as single
asm
  fild word ptr [esp+4]
  push 10000
  fild dword ptr [esp]
  fdivp
  pop eax
  ret
end asm
end function

Print "Short=";GetHalf(31416)
Sleep
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Short Single?

Post by MrSwiss »

BasicJedi wrote:For example when printing they are too long, ( always need to round it or use PRINT USING)
The printing issue can pretty easily be fixed, by using a 'self written' custom function.
Deals with Double but can also take Single.
Decimal digits after the delimiter, can be set, from 0 to 9 (default: 2).
It adds "0"'s in case the fraction is shorter than 'ndec'.
(this alowes to print right-justified values, positioned below each other)

NOTE: only the integer return is rounded (ndec = 0), all else is just "chopped off".

This is what I currently use:

Code: Select all

' Fit2nDec_proc.bas -- (c) 2021-05-15, MrSwiss
'

Function Fit2nDec( _                    ' chop double to set number of decimals
    ByVal v_in  As Double,   _          ' input value
    ByVal ndec  As ULong = 2 _          ' number decimals (default = 2)
    ) As String
	If ndec > 9 Then ndec = 9           ' force max. number of decimals
    
	If ndec = 0 Then                    ' when no fraction wanted ...
	    Return Str(CLngInt(v_in))       ' string (rounded longint)
	Else
	    Var fs = Str(Frac(v_in))        ' string
	    Var s  = Right(fs, Len(fs) - IIf(v_in < 0.0, 3, 2)) ' string
	    Var ls = Len(s)                 ' integer
	    If ls > ndec Then s = Left(s, ndec) ' chop fraction off (no rounding)
        While ls < ndec                 ' if fraction to short
            s += "0" : ls += 1          ' add zero | increment ls
        Wend
	    Return Str(Fix(v_in)) + "." + s ' concatenate result
	End If
End Function
jevans4949
Posts: 1186
Joined: May 08, 2006 21:58
Location: Crewe, England

Re: Short Single?

Post by jevans4949 »

There is an IEEE specification for decimal (as opposed to binary) floating point numbers, but I don't know if anybody has ever implemented it, in software or hardware.
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Short Single?

Post by marcov »

jevans4949 wrote:There is an IEEE specification for decimal (as opposed to binary) floating point numbers, but I don't know if anybody has ever implemented it, in software or hardware.
BCD floating point hardware existed yes. Even x87 has some (load/store) support:
Wikipedia wrote: In x87
See also: Intel 8087 § IEEE floating-point standard

The x87 coprocessor has BCD support in the form of a pair of load (FBLD) and store-and-pop (FBSTP) instructions. The former loads a 80-bit BCD integer into the FPU, while the latter writes a FPU value as a 80-bit integer value into the memory. Inside of the FPU, the values are stored as normal x87 extended-precision floats. Unlike the integer-facing versions, the two instructions remain available in long mode.
Note to OP: if you don't really need floating point, a fixed point value is sometimes also used. This is less dynamic, but if all you want is multiplying integers by small factors (e.g. 1.3) then it can be useful and efficient on embedded systems.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: Short Single?

Post by srvaldez »

hello jevans4949
D.J.Peters wrote a fixed-point package viewtopic.php?p=200294#p200294
Intel wrote and released a BCD math library viewtopic.php?f=14&t=29203
IBM also came out with DecNumber and there's mpdecimal, but the library by Intel is the most versatile
jevans4949
Posts: 1186
Joined: May 08, 2006 21:58
Location: Crewe, England

Re: Short Single?

Post by jevans4949 »

I stand enlightened.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Short Single?

Post by dodicat »

Going the other way, it looks like the crt double has one more place than the fb double.

Code: Select all

#include "crt.bi"

Function _str(Byval x As Double) As string
      static As zstring * 32 t
      sprintf(t,"%.30f",x)
      if instr(t,".") then 
      t=rtrim(t,"0")
      Return rtrim(t,".")
      else
      return t
      end if
End Function

#define _round(x,N) rtrim(rtrim(left(_str((x)+(.5*sgn((x)))/(10^(N))),instr(_str((x)+(.5*sgn((x)))/(10^(N))),".")+(N)),"0"),".")

dim as string s,b
print "rounded(5)";tab(25);"number";tab(50);"crt number";tab(80);"difference"
for x as long=1 to 500
    var d=(rnd-rnd)/1000
    var f=(rnd-rnd)*10000000000
    if rnd>.5 then
        s=_round(d,5)
print s;tab(25);d;tab(50);_str(d);tab(80);val(_str(d))-d
else
    b=_round(f,5)
 print b;tab(25);f;tab(50);_str(f);tab(80);val(_str(f))-f'val(b)-f
 end if
next
sleep

 
 
  
Post Reply