Author Topic: 4 / 6 = .67  (Read 10084 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: 4 / 6 = .67
« Reply #30 on: February 03, 2020, 02:16:46 pm »
And one additional point for you guys to remember:

Code: [Select]
DIM A AS DOUBLE
DIM b AS _FLOAT

A# = 0.12345678901234567890
b## = 0.12345678901234567890

PRINT A#
PRINT b##

I can’t stress this point enough: PRINT IS UNRELIABLE FOR VALUE COMPARISONS..

PRINT is probably the most complicated and overly convoluted piece of code in all of QB64.  You want a nice headache??  Go into QB64.bas and libqb.cpp and try and decode how the BLEEP Galleon has it doing what it does.  PRINT converts, inverts, reverts, exverts, introverts, unverts, and farts on whatever you send it, and then by some presto magicunknownicus it displays stuff to the screen — but that’s at whatever precision level PRINT wants to display it at.

x =  0.0000000000000000001  *might* print 0 to the screen, making you think, “OH!  I went beyond precision limits!”  Then you might write FOR I = 1 TO 10: x = x * 2: NEXT.  At this point, when you get x, it might print something like 1D-8...   If the internal value was actually 0, then 0 * 0 ten times would still be 0, but the answer doesn’t show that.

The internal value and the printed value aren’t always the same, just from however PRINT is doing what it does.

With the above, you might try “IF A# = b## THEN”, and find that the two values aren’t necessarily the same.  A# may truncate the precision before b## does, giving you different values.

I’m not certain at what depth of precision the values change, but I’m certain I’ve experienced the issue in code before in the past.  _FLOAT holds precision greater than PRINT displays, so you can’t always trust it as a value comparison tool.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: 4 / 6 = .67
« Reply #31 on: February 03, 2020, 03:05:57 pm »
Well, thank you Steve. Then there is actually one, third way. The thread concerns the question - the result of the divide. This can be programmed. So:
(it is writed for integers)

Code: QB64: [Select]
  1.  
  2.  
  3. PRINT LongDecimal$(4, 6, 500)
  4. PRINT LongDecimal$(22, 7, 1000)
  5.  
  6. FUNCTION LongDecimal$ (numerator, denominator, places)
  7.     i = numerator \ denominator
  8.     LongDecimal$ = STR$(i) + "."
  9.     DO UNTIL act = places
  10.         act = act + 1
  11.         d = (numerator MOD denominator) * 10
  12.         LongDecimal$ = LongDecimal$ + LTRIM$(STR$(d \ denominator))
  13.         numerator = d MOD denominator
  14.     LOOP
  15.  
« Last Edit: February 03, 2020, 03:22:02 pm by Petr »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: 4 / 6 = .67
« Reply #32 on: February 03, 2020, 10:43:19 pm »
Hey Petr, I like!

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: 4 / 6 = .67
« Reply #33 on: February 03, 2020, 11:39:09 pm »
Oh, I did not know. Broke might imply it did work at one time (and could be fixed).

How broke? is it just is the same as DOUBLE? or worse?
for the most part, the precision is the same as double, in 32-bit the mantissa is more accurate but the range is the same as double, but the range should be much larger
Quote from: Wikipedia link=https://en.wikipedia.org/wiki/Extended_precision
The 80-bit floating point format has a range (including subnormals) from approximately 3.65×10−4951 to 1.18×104932. Although log10(264) ≅ 19.266, this format is usually described as giving approximately eighteen significant digits of precision.
see https://www.qb64.org/forum/index.php?topic=1957.msg111896#msg111896
post and onward https://www.qb64.org/forum/index.php?topic=1798.msg110439#msg110439
thread https://www.qb64.org/forum/index.php?topic=1167.msg103597#msg103597

try this
Code: [Select]
DIM a AS _FLOAT, b AS _FLOAT
a = 1
FOR k = 1 TO 175
    a = a * k
NEXT

PRINT a
b = LOG(a)
PRINT b
b = a / 10000000000##
PRINT b
PRINT "the factorial of 175 = 1.1244494910857363283041099386422042552 E318"
the division works but not the log function, so I am guessing that the basic 4 arithmetic operators work on Float in QB64 32-bit version but nothing else.
« Last Edit: February 04, 2020, 03:24:47 am by jack »

Offline MLambert

  • Forum Regular
  • Posts: 115
    • View Profile
Re: 4 / 6 = .67
« Reply #34 on: February 04, 2020, 06:58:20 am »
Just as well that I didn't ask for 1/0 round.

Thks again.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: 4 / 6 = .67
« Reply #35 on: February 04, 2020, 07:34:40 am »
for the most part, the precision is the same as double, in 32-bit the mantissa is more accurate but the range is the same as double, but the range should be much largersee https://www.qb64.org/forum/index.php?topic=1957.msg111896#msg111896
post and onward https://www.qb64.org/forum/index.php?topic=1798.msg110439#msg110439
thread https://www.qb64.org/forum/index.php?topic=1167.msg103597#msg103597

try this
Code: [Select]
DIM a AS _FLOAT, b AS _FLOAT
a = 1
FOR k = 1 TO 175
    a = a * k
NEXT

PRINT a
b = LOG(a)
PRINT b
b = a / 10000000000##
PRINT b
PRINT "the factorial of 175 = 1.1244494910857363283041099386422042552 E318"
the division works but not the log function, so I am guessing that the basic 4 arithmetic operators work on Float in QB64 32-bit version but nothing else.

_FLOAT isn’t “broke” on 64-bit versions.  You need to take a moment to read up on the long double variable type to try and understand the difference in behavior: https://en.wikipedia.org/wiki/Long_double

Quote
In C and related programming languages, long double refers to a floating-point data type that is often more precise than double-precision though the language standard only requires it to be at least as precise as double. As with C's other floating-point types, it may not necessarily map to an IEEE format.

The precision results you see with _FLOAT depends heavily upon your system, the compiler you’re using, and sometimes even which option flags you have set with your compiler.

It’s not anything inside QB64 which is “broken”.  It’s simply the nature of a long double data type (_FLOAT).

_FLOATs are *required* to be as precise as doubles, but often offer more precision than that.  You can’t expect anything more from your programs than that, unless you want to write your own math routines or go to string math.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: 4 / 6 = .67
« Reply #36 on: February 04, 2020, 11:46:00 am »
@SMcNeill
QB64 on Windows uses mingw g++ compiler, and it supports 80-bit long double
Code: [Select]
#define __USE_MINGW_ANSI_STDIO 1
// or pass the following directive on the compile command
// -D__USE_MINGW_ANSI_STDIO
#include <stdio.h>

int main()
{
union ldb{
unsigned short m[8];
long double ld;
};
typedef union ldb ldbl;

ldbl x;
x.ld=3.1415926535897932384626433832795L;

printf("%24.19Lf\n",x.ld);

printf("%X",x.m[4]);
printf(" %X",x.m[3]);
printf("%X",x.m[2]);
printf("%X",x.m[1]);
printf("%X",x.m[0]);
return 0;
}
output
   3.1415926535897932385
4000 C90FDAA22168C235
here's QB64 snippet that prints the hex value of Pi
Code: [Select]
f## = 3.1415926535897932384626433832795##
DIM float_pointer AS _MEM
DIM mantissa AS _UNSIGNED _INTEGER64
DIM exponent AS _UNSIGNED INTEGER

float_pointer = _MEM(f##)
mantissa = _MEMGET(float_pointer, float_pointer.OFFSET + 0, _UNSIGNED _INTEGER64)
exponent = _MEMGET(float_pointer, float_pointer.OFFSET + 8, _UNSIGNED INTEGER)
_MEMFREE float_pointer
PRINT HEX$(exponent), HEX$(mantissa)
output
4000 C90FDAA22168C235
this should be obvious that the hex representation are the same as the one used in the C code, however, most of the functionality of 80-bit Float is not implemented, therefore _Float IS BROKEN so why deny it