QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: MLambert on February 01, 2020, 04:34:47 am

Title: 4 / 6 = .67
Post by: MLambert on February 01, 2020, 04:34:47 am
I am sure there is an easy way to do this without string manipulation ... how ?

I want 2 decimal not .66666666667  when I divide 2 numbers.

Thks,

Mike
Title: Re: 4 / 6 = .67
Post by: krovit on February 01, 2020, 05:59:26 am
Code: QB64: [Select]
  1. ? 4/6
  2. ?
  3.  
  4. calc=4/6
  5. ? calc
  6. ?
  7.  
  8. calc#=4/6
  9. ? calc#
  10. ?
  11.  
  12. print using" #.##"; calc#
  13. ?
  14.  
  15. ? VAL(mid$(str$(calc#),instr(str$(calc#),"."),3))
  16. ?
  17.  
  18. ? val(mid$(str$(calc#+0.005),instr(str$(calc#+0.005),"."),3))
  19. ?
  20.  
  21.  
  22.  

Hello Mike,
it's a little rough and primitive but maybe it helps to understand (but maybe you already knew).

it's not a complication of QB64... is the typical system used by all programming languages.

Maybe I'm wrong but I don't think there is a direct command of the type: round-to-the-second-digit-this-number or the-result-of-this-calculation but you can do it yourself by creating a function.

Put line 18 code (appropriately modified) in a function and it all will become simple.




Title: Re: 4 / 6 = .67
Post by: SMcNeill on February 01, 2020, 06:49:00 am
X = INT(X * 100) / 100 to truncate at 2 decimal places.

X = INT(X * 100 + .5) / 100 to round at 2 decimal places.
Title: Re: 4 / 6 = .67
Post by: krovit on February 01, 2020, 07:07:04 am
Yes, it's the super classic system (which I also use, of course, like everyone else)

My contribution is a complication but made in order to illustrate. In fact, I'd better keep quiet ;)

Title: Re: 4 / 6 = .67
Post by: MLambert on February 01, 2020, 09:49:07 am
Many thks ... I haven't used masking for a long time and couldn't find/see INT.

Mike
Title: Re: 4 / 6 = .67
Post by: MLambert on February 01, 2020, 10:08:45 am
Hi,

tried the INT version ... 4/3 = 133.3333 ?? both INT solutions give me the same answer

i.e.  X = INT(4 * 100 + .5) / 3  or

X = INT(4 * 100) / 3

I would like 1.33 to 2 decimal places

and 4/6 = 1.67 and this rounded

I have tried the string manipulations and it seems to work fine.

Mike
Title: Re: 4 / 6 = .67
Post by: Qwerkey on February 01, 2020, 10:30:03 am
X = INT(X * 100 + .5) / 100 to round at 2 decimal places.

Seems unnecessarily complicated?  Why not the simple:
X = CINT(X * 100) / 100 to round at 2 decimal places?
Title: Re: 4 / 6 = .67
Post by: SMcNeill on February 01, 2020, 11:21:47 am
Seems unnecessarily complicated?  Why not the simple:
X = CINT(X * 100) / 100 to round at 2 decimal places?

Depends on if X * 100 is an integer value, or larger.  ;)
Title: Re: 4 / 6 = .67
Post by: MLambert on February 02, 2020, 03:19:53 am
Hi Krovit,

Using your method ... but it only returns the decimal places ... I need the whole number as well.

5/3 = .67  this is great .. but I want the 1.67.

Thks,

Mike
Title: Re: 4 / 6 = .67
Post by: STxAxTIC on February 02, 2020, 05:32:04 am
Code: QB64: [Select]
  1. a = 5
  2. b = 3
  3.  
  4. r = a / b
  5. c = INT(r)
  6. t = INT(100 * (r - c) + .5) / 100
  7.  
  8. PRINT c + t
Title: Re: 4 / 6 = .67
Post by: MWheatley on February 02, 2020, 06:56:49 am
X = INT(X * 100) / 100 to truncate at 2 decimal places.

X = INT(X * 100 + .5) / 100 to round at 2 decimal places.

This is how I've always done it, for 40+ years.  Most occasions, it's only once or twice at most in a program, ie for printing results to either screen or printer.  The idea of a function hadn't even occurred to me, because the usage is so rare.

I'd be intrigued to know if anybody has seen the value in rounding via a function, though.

Malcolm
Title: Re: 4 / 6 = .67
Post by: Petr on February 02, 2020, 08:08:38 am
This is way without string conversions. Function parameters are: decimal number, lenght

Code: QB64: [Select]
  1. PRINT LNUM(0.0001, 4)
  2. PRINT 22 / 7
  3. PRINT LNUM(22 / 7, 1)
  4. PRINT LNUM(22 / 7, 5)
  5.  
  6.  
  7. FUNCTION LNUM! (num!, lenght)
  8.     '1.2345, 2  =>  1.23
  9.     integernum = num \ 1
  10.     decimalnum = num / 1 - num! \ 1
  11.     n = 10 ^ lenght
  12.     newdecimalnum = decimalnum * n
  13.     newdecimalnum = INT(newdecimalnum)  'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  14.     newdecimalnum = newdecimalnum / n
  15.     LNUM = integernum + newdecimalnum
  16.  
  17.  
Title: Re: 4 / 6 = .67
Post by: SMcNeill on February 02, 2020, 08:44:00 am
Aren’t you guys just overcomplicating things?  A single line function is all anyone would ever really need...

Code: [Select]
FUNCTION RoundTo## (Num AS _FLOAT, Precision AS INTEGER)
    RoundTo = INT(Num * 10 ^ Precision + .5) / 10 ^ Precision
END FUNCTION
Title: Re: 4 / 6 = .67
Post by: Petr on February 02, 2020, 08:57:13 am
OK. This is the last thing I added to this forum.
Title: Re: 4 / 6 = .67
Post by: SMcNeill on February 02, 2020, 09:14:42 am
Hi,

tried the INT version ... 4/3 = 133.3333 ?? both INT solutions give me the same answer

i.e.  X = INT(4 * 100 + .5) / 3  or

X = INT(4 * 100) / 3

I would like 1.33 to 2 decimal places

and 4/6 = 1.67 and this rounded

I have tried the string manipulations and it seems to work fine.

Mike

 X = INT(X * 100 + .5) / 100 <— The original statement, which you misapplied here:  X = INT(4 * 100 + .5) / 3

The correct way would be either:
X = 4 / 3
X = INT( X * 100 + .5) / 100

Or:

X = INT( 4 / 3 * 100 + .5) / 100
Title: Re: 4 / 6 = .67
Post by: bplus on February 02, 2020, 11:47:09 am
Hi Krovit,

Using your method ... but it only returns the decimal places ... I need the whole number as well.

5/3 = .67  this is great .. but I want the 1.67.

Thks,

Mike


Maybe if you see the actual numbers in the formula Steve gave you?
Code: QB64: [Select]
  1. PRINT INT(4 / 6 * 100 + .5) / 100
  2. PRINT INT(5 / 3 * 100 + .5) / 100
  3.  
Title: Re: 4 / 6 = .67
Post by: MWheatley on February 02, 2020, 03:20:50 pm
This is way without string conversions. Function parameters are: decimal number, lenght

Code: QB64: [Select]
  1. PRINT LNUM(0.0001, 4)
  2. PRINT 22 / 7
  3. PRINT LNUM(22 / 7, 1)
  4. PRINT LNUM(22 / 7, 5)
  5.  
  6.  
  7. FUNCTION LNUM! (num!, lenght)
  8.     '1.2345, 2  =>  1.23
  9.     integernum = num \ 1
  10.     decimalnum = num / 1 - num! \ 1
  11.     n = 10 ^ lenght
  12.     newdecimalnum = decimalnum * n
  13.     newdecimalnum = INT(newdecimalnum)  'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  14.     newdecimalnum = newdecimalnum / n
  15.     LNUM = integernum + newdecimalnum
  16.  
  17.  

Hey -- thanks for that.  That's really clear.  I like code that I can understand!

Malcolm
Title: Re: 4 / 6 = .67
Post by: Petr on February 02, 2020, 04:00:21 pm
Thank You, MWheatley. I will never use the insanity in one row. Source code clearity is much better than small source code size.
Title: Re: 4 / 6 = .67
Post by: MLambert on February 03, 2020, 04:26:12 am
Thank you everyone.

Mike
Title: Re: 4 / 6 = .67
Post by: Dimster on February 03, 2020, 10:36:47 am
I added the following to the code and it seems it will not produce a decimal place beyond 6. I'm not sure why that would be.

Code: QB64: [Select]
  1. PRINT LNUM(0.0001, 4)
  2. PRINT 22 / 7
  3. PRINT LNUM(22 / 7, 1)
  4. PRINT LNUM(22 / 7, 5)
  5.  
  6. PRINT "1 decimal place   ";
  7. PRINT LNUM(22 / 7, 1)
  8. PRINT "2 decimal places  ";
  9. PRINT LNUM(22 / 7, 2)
  10. PRINT "3 decimal places  ";
  11. PRINT LNUM(22 / 7, 3)
  12. PRINT "4 decimal places  ";
  13. PRINT LNUM(22 / 7, 4)
  14. PRINT "5 decimal places  ";
  15. PRINT LNUM(22 / 7, 5)
  16. PRINT "6 decimal places  ";
  17. PRINT LNUM(22 / 7, 6)
  18. PRINT "7 decimal places  ";
  19. PRINT LNUM(22 / 7, 7)
  20. PRINT "8 decimal places  ";
  21. PRINT LNUM(22 / 7, 8)
  22. PRINT "9 decimal places  ";
  23. PRINT LNUM(22 / 7, 9)
  24. PRINT "10 decimal places ";
  25. PRINT LNUM(22 / 7, 10)
  26.  
  27.  
  28.  
  29.  
  30. FUNCTION LNUM! (num!, lenght)
  31.     '1.2345, 2  =>  1.23
  32.     integernum = num \ 1
  33.     decimalnum = num / 1 - num! \ 1
  34.     n = 10 ^ lenght
  35.     newdecimalnum = decimalnum * n
  36.     newdecimalnum = INT(newdecimalnum) 'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  37.     newdecimalnum = newdecimalnum / n
  38.     LNUM = integernum + newdecimalnum
Title: Re: 4 / 6 = .67
Post by: bplus on February 03, 2020, 11:47:46 am
I added the following to the code and it seems it will not produce a decimal place beyond 6. I'm not sure why that would be.

Code: QB64: [Select]
  1. PRINT LNUM(0.0001, 4)
  2. PRINT 22 / 7
  3. PRINT LNUM(22 / 7, 1)
  4. PRINT LNUM(22 / 7, 5)
  5.  
  6. PRINT "1 decimal place   ";
  7. PRINT LNUM(22 / 7, 1)
  8. PRINT "2 decimal places  ";
  9. PRINT LNUM(22 / 7, 2)
  10. PRINT "3 decimal places  ";
  11. PRINT LNUM(22 / 7, 3)
  12. PRINT "4 decimal places  ";
  13. PRINT LNUM(22 / 7, 4)
  14. PRINT "5 decimal places  ";
  15. PRINT LNUM(22 / 7, 5)
  16. PRINT "6 decimal places  ";
  17. PRINT LNUM(22 / 7, 6)
  18. PRINT "7 decimal places  ";
  19. PRINT LNUM(22 / 7, 7)
  20. PRINT "8 decimal places  ";
  21. PRINT LNUM(22 / 7, 8)
  22. PRINT "9 decimal places  ";
  23. PRINT LNUM(22 / 7, 9)
  24. PRINT "10 decimal places ";
  25. PRINT LNUM(22 / 7, 10)
  26.  
  27.  
  28.  
  29.  
  30. FUNCTION LNUM! (num!, lenght)
  31.     '1.2345, 2  =>  1.23
  32.     integernum = num \ 1
  33.     decimalnum = num / 1 - num! \ 1
  34.     n = 10 ^ lenght
  35.     newdecimalnum = decimalnum * n
  36.     newdecimalnum = INT(newdecimalnum) 'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  37.     newdecimalnum = newdecimalnum / n
  38.     LNUM = integernum + newdecimalnum

Maybe _FLOAT instead of single will buy more decimal places.

yep!
Code: QB64: [Select]
  1. PRINT LNUM(0.0001, 4)
  2. PRINT 22 / 7
  3. PRINT LNUM(22 / 7, 1)
  4. PRINT LNUM(22 / 7, 5)
  5.  
  6. PRINT "1 decimal place   ";
  7. PRINT LNUM(22 / 7, 1)
  8. PRINT "2 decimal places  ";
  9. PRINT LNUM(22 / 7, 2)
  10. PRINT "3 decimal places  ";
  11. PRINT LNUM(22 / 7, 3)
  12. PRINT "4 decimal places  ";
  13. PRINT LNUM(22 / 7, 4)
  14. PRINT "5 decimal places  ";
  15. PRINT LNUM(22 / 7, 5)
  16. PRINT "6 decimal places  ";
  17. PRINT LNUM(22 / 7, 6)
  18. PRINT "7 decimal places  ";
  19. PRINT LNUM(22 / 7, 7)
  20. PRINT "8 decimal places  ";
  21. PRINT LNUM(22 / 7, 8)
  22. PRINT "9 decimal places  ";
  23. PRINT LNUM(22 / 7, 9)
  24. PRINT "10 decimal places ";
  25. PRINT LNUM(22 / 7, 10)
  26.  
  27.  
  28.  
  29.  
  30. 'FUNCTION LNUM! (num!, lenght)
  31. '    '1.2345, 2  =>  1.23
  32. '    integernum = num \ 1
  33. '    decimalnum = num / 1 - num! \ 1
  34. '    n = 10 ^ lenght
  35. '    newdecimalnum = decimalnum * n
  36. '    newdecimalnum = INT(newdecimalnum) 'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  37. '    newdecimalnum = newdecimalnum / n
  38. '    LNUM = integernum + newdecimalnum
  39. 'END FUNCTION
  40.  
  41.  
  42. FUNCTION LNUM## (num##, leng)
  43.     LNUM## = INT(num## * 10 ^ leng + .5) / 10 ^ leng
  44.  
  45.  
Title: Re: 4 / 6 = .67
Post by: Petr on February 03, 2020, 11:54:15 am
Its because it is SINGLE precision. Try DOUBLE, or FLOAT:

Double:

Code: QB64: [Select]
  1. PRINT LNUM(0.0001, 4)
  2. PRINT 22 / 7
  3. PRINT LNUM(22 / 7, 1)
  4. PRINT LNUM(22 / 7, 5)
  5.  
  6. PRINT "1 decimal place   ";
  7. PRINT LNUM(22 / 7, 1)
  8. PRINT "2 decimal places  ";
  9. PRINT LNUM(22 / 7, 2)
  10. PRINT "3 decimal places  ";
  11. PRINT LNUM(22 / 7, 3)
  12. PRINT "4 decimal places  ";
  13. PRINT LNUM(22 / 7, 4)
  14. PRINT "5 decimal places  ";
  15. PRINT LNUM(22 / 7, 5)
  16. PRINT "6 decimal places  ";
  17. PRINT LNUM(22 / 7, 6)
  18. PRINT "7 decimal places  ";
  19. PRINT LNUM(22 / 7, 7)
  20. PRINT "8 decimal places  ";
  21. PRINT LNUM(22 / 7, 8)
  22. PRINT "9 decimal places  ";
  23. PRINT LNUM(22 / 7, 9)
  24. PRINT "10 decimal places ";
  25. PRINT LNUM(22 / 7, 10)
  26.  
  27.  
  28.  
  29.  
  30. FUNCTION LNUM# (num#, lenght)
  31.     '1.2345, 2  =>  1.23
  32.     integernum# = num# \ 1
  33.     decimalnum# = num# / 1 - num# \ 1
  34.     n = 10 ^ lenght
  35.     newdecimalnum# = decimalnum# * n
  36.     newdecimalnum# = INT(newdecimalnum#) 'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  37.     newdecimalnum# = newdecimalnum# / n
  38.     LNUM# = integernum# + newdecimalnum#
  39.  
  40.  

or FLOAT:

Code: QB64: [Select]
  1.  
  2. PRINT LNUM(0.0001, 4)
  3. PRINT 22 / 7
  4. PRINT LNUM(22 / 7, 1)
  5. PRINT LNUM(22 / 7, 5)
  6.  
  7. PRINT "1 decimal place   ";
  8. PRINT LNUM(22 / 7, 1)
  9. PRINT "2 decimal places  ";
  10. PRINT LNUM(22 / 7, 2)
  11. PRINT "3 decimal places  ";
  12. PRINT LNUM(22 / 7, 3)
  13. PRINT "4 decimal places  ";
  14. PRINT LNUM(22 / 7, 4)
  15. PRINT "5 decimal places  ";
  16. PRINT LNUM(22 / 7, 5)
  17. PRINT "6 decimal places  ";
  18. PRINT LNUM(22 / 7, 6)
  19. PRINT "7 decimal places  ";
  20. PRINT LNUM(22 / 7, 7)
  21. PRINT "8 decimal places  ";
  22. PRINT LNUM(22 / 7, 8)
  23. PRINT "9 decimal places  ";
  24. PRINT LNUM(22 / 7, 9)
  25. PRINT "10 decimal places ";
  26. PRINT LNUM(22 / 7, 10)
  27.  
  28.  
  29.  
  30.  
  31. FUNCTION LNUM## (num##, lenght)
  32.     '1.2345, 2  =>  1.23
  33.     integernum## = num## \ 1
  34.     decimalnum## = num## / 1 - num## \ 1
  35.     n = 10 ^ lenght
  36.     newdecimalnum## = decimalnum## * n
  37.     newdecimalnum## = INT(newdecimalnum##) 'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  38.     newdecimalnum## = newdecimalnum## / n
  39.     LNUM## = integernum## + newdecimalnum##
  40.  
  41.  
Title: Re: 4 / 6 = .67
Post by: bplus on February 03, 2020, 12:05:24 pm
Its because it is SINGLE precision. Try DOUBLE, or FLOAT:

Double:

Code: QB64: [Select]
  1. PRINT LNUM(0.0001, 4)
  2. PRINT 22 / 7
  3. PRINT LNUM(22 / 7, 1)
  4. PRINT LNUM(22 / 7, 5)
  5.  
  6. PRINT "1 decimal place   ";
  7. PRINT LNUM(22 / 7, 1)
  8. PRINT "2 decimal places  ";
  9. PRINT LNUM(22 / 7, 2)
  10. PRINT "3 decimal places  ";
  11. PRINT LNUM(22 / 7, 3)
  12. PRINT "4 decimal places  ";
  13. PRINT LNUM(22 / 7, 4)
  14. PRINT "5 decimal places  ";
  15. PRINT LNUM(22 / 7, 5)
  16. PRINT "6 decimal places  ";
  17. PRINT LNUM(22 / 7, 6)
  18. PRINT "7 decimal places  ";
  19. PRINT LNUM(22 / 7, 7)
  20. PRINT "8 decimal places  ";
  21. PRINT LNUM(22 / 7, 8)
  22. PRINT "9 decimal places  ";
  23. PRINT LNUM(22 / 7, 9)
  24. PRINT "10 decimal places ";
  25. PRINT LNUM(22 / 7, 10)
  26.  
  27.  
  28.  
  29.  
  30. FUNCTION LNUM# (num#, lenght)
  31.     '1.2345, 2  =>  1.23
  32.     integernum# = num# \ 1
  33.     decimalnum# = num# / 1 - num# \ 1
  34.     n = 10 ^ lenght
  35.     newdecimalnum# = decimalnum# * n
  36.     newdecimalnum# = INT(newdecimalnum#) 'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  37.     newdecimalnum# = newdecimalnum# / n
  38.     LNUM# = integernum# + newdecimalnum#
  39.  
  40.  

or FLOAT:

Code: QB64: [Select]
  1.  
  2. PRINT LNUM(0.0001, 4)
  3. PRINT 22 / 7
  4. PRINT LNUM(22 / 7, 1)
  5. PRINT LNUM(22 / 7, 5)
  6.  
  7. PRINT "1 decimal place   ";
  8. PRINT LNUM(22 / 7, 1)
  9. PRINT "2 decimal places  ";
  10. PRINT LNUM(22 / 7, 2)
  11. PRINT "3 decimal places  ";
  12. PRINT LNUM(22 / 7, 3)
  13. PRINT "4 decimal places  ";
  14. PRINT LNUM(22 / 7, 4)
  15. PRINT "5 decimal places  ";
  16. PRINT LNUM(22 / 7, 5)
  17. PRINT "6 decimal places  ";
  18. PRINT LNUM(22 / 7, 6)
  19. PRINT "7 decimal places  ";
  20. PRINT LNUM(22 / 7, 7)
  21. PRINT "8 decimal places  ";
  22. PRINT LNUM(22 / 7, 8)
  23. PRINT "9 decimal places  ";
  24. PRINT LNUM(22 / 7, 9)
  25. PRINT "10 decimal places ";
  26. PRINT LNUM(22 / 7, 10)
  27.  
  28.  
  29.  
  30.  
  31. FUNCTION LNUM## (num##, lenght)
  32.     '1.2345, 2  =>  1.23
  33.     integernum## = num## \ 1
  34.     decimalnum## = num## / 1 - num## \ 1
  35.     n = 10 ^ lenght
  36.     newdecimalnum## = decimalnum## * n
  37.     newdecimalnum## = INT(newdecimalnum##) 'or comment this row and rewrite it as  newdecimalnum = newdecimalnum \ 1 for rounding outputs.
  38.     newdecimalnum## = newdecimalnum## / n
  39.     LNUM## = integernum## + newdecimalnum##
  40.  
  41.  

Petr, yours isn't rounding and more complicated than needs be, IMHO ;-))
Title: Re: 4 / 6 = .67
Post by: Petr on February 03, 2020, 12:25:27 pm
Too Complicated... It's difficult with you, guys, here. You still have some reservations :) Look, BPlus, it doesn't rounding because I didn't mean to. If you look at my source code, the row where this is:

  newdecimalnum ## = INT (newdecimalnum ##) 'or comment this row and rewrite it as newdecimalnum = newdecimalnum \ 1 for rounding outputs.

It gives an answer. When you rewrite this, you get a rounded output.
But what surprises me. Neither mine nor Steve's function returns more than a 15-digit decimal. Why? Although a larger decimal number does not seem to be meaningful, it still does the same outputs. That is, both DOUBLE and FLOAT return the same output?

Try this:

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

A# = 0.12345678901234567890
b## = 0.12345678901234567890

PRINT A#
PRINT b##

Why?
Title: Re: 4 / 6 = .67
Post by: jack on February 03, 2020, 12:52:55 pm
That is, both DOUBLE and FLOAT return the same output?

Try this:

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

A# = 0.12345678901234567890
b## = 0.12345678901234567890

PRINT A#
PRINT b##

Why?
Float is broken, you may as well stick to double and forget about Float
Title: Re: 4 / 6 = .67
Post by: bplus on February 03, 2020, 01:11:36 pm
Float is broken, you may as well stick to double and forget about Float

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?
Title: Re: 4 / 6 = .67
Post by: SMcNeill on February 03, 2020, 01:24:30 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?

DOUBLE is stored as an 8 byte value in memory.
_FLOAT is stored as a 32 byte value — but only 10 bytes are actually used.  The other 22  bytes are basically reserved for future compatibility/use.

_FLOATS hold a little more precision than DOUBLE, but not much more (10 bytes verses 8), and they use 4x the memory.  Unless you absolutely need that extra precision, or unless you want to prepare for future implementation, in most cases you’re just as well off using DOUBLE as you are _FLOAT.

(One other cavet which I’ve noticed with _FLOAT: it often processes faster than double as many internal routines seem geared to work with float natively, and they don’t need to convert type values/offsets to process properly.  This may just be a result of the processes I use personally, so others may have different results, but it tends to hold true for me that float is faster than double/single.)
Title: Re: 4 / 6 = .67
Post by: bplus on February 03, 2020, 01:30:46 pm
Too Complicated... It's difficult with you, guys, here. You still have some reservations :) Look, BPlus, it doesn't rounding because I didn't mean to. If you look at my source code, the row where this is:

  newdecimalnum ## = INT (newdecimalnum ##) 'or comment this row and rewrite it as newdecimalnum = newdecimalnum \ 1 for rounding outputs.

It gives an answer. When you rewrite this, you get a rounded output.
But what surprises me. Neither mine nor Steve's function returns more than a 15-digit decimal. Why? Although a larger decimal number does not seem to be meaningful, it still does the same outputs. That is, both DOUBLE and FLOAT return the same output?

Try this:

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

A# = 0.12345678901234567890
b## = 0.12345678901234567890

PRINT A#
PRINT b##

Why?

Hi Petr,

In paper today it said I could argue with my friends, I hope

rounding seems to me the only way to get 4/6 = .67

overly complicated because it takes you 6 lines to do what can be done in one.

I rest my case.

I will buy you a beer if we ever meet :) and we can laugh at this BS.
Title: Re: 4 / 6 = .67
Post by: Petr on February 03, 2020, 01:45:21 pm
Thank you, Jack and Steve for explanation and BPlus for you nice answer.

I apologize for my exaggerated reactions, perhaps i give some form of male menstruation or something like that... alone don´t know.
Title: Re: 4 / 6 = .67
Post by: STxAxTIC on February 03, 2020, 02:13:32 pm
Its testosterone, I can attest(icle)
Title: Re: 4 / 6 = .67
Post by: SMcNeill 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.
Title: Re: 4 / 6 = .67
Post by: Petr 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.  
Title: Re: 4 / 6 = .67
Post by: bplus on February 03, 2020, 10:43:19 pm
Hey Petr, I like!
Title: Re: 4 / 6 = .67
Post by: jack 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.
Title: Re: 4 / 6 = .67
Post by: MLambert on February 04, 2020, 06:58:20 am
Just as well that I didn't ask for 1/0 round.

Thks again.
Title: Re: 4 / 6 = .67
Post by: SMcNeill 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.
Title: Re: 4 / 6 = .67
Post by: jack 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