Decimal point problem (was: Very noob doubt is driving me crazy)

Just starting out? Need help? Post your questions and find answers here.
eNano
User
User
Posts: 13
Joined: Wed Jun 05, 2024 4:48 pm

Decimal point problem (was: Very noob doubt is driving me crazy)

Post by eNano »

A very simple doubt that I can´t find an answer:
If I debug this:

Code: Select all

Debug 538.0 * 0.0254
why the result is 13.6652000000000004575895218 when after the 4th decimal all should be zero?
I really appreciate any help
BarryG
Addict
Addict
Posts: 4123
Joined: Thu Apr 18, 2019 8:17 am

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by BarryG »

You need to specify that the value be of Double type when using the Debug command:

Code: Select all

Debug StrD(538.0 * 0.0254) ; Outputs 13.6652
See the bottom of this page in the manual - > https://www.purebasic.com/documentation ... ables.html
User avatar
TI-994A
Addict
Addict
Posts: 2698
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by TI-994A »

eNano wrote: Fri Aug 30, 2024 12:20 amwhy the result is 13.6652000000000004575895218 when after the 4th decimal all should be zero?
Hi eNano, and welcome to PureBasic! :D

This is the inherent nature of floating point numbers. Even if a string representation of a double or float is converted, the results would be the same:

Code: Select all

Debug ValD("123.456")   ; 123.4560000000000030695446185
Debug ValF("123.456")   ; 123.45600128173828

The PureBasic StrD() and StrF() functions are purpose-built for such cases, and would actually round-off the values with arithmetic accuracy:

Code: Select all

Debug StrD(123.456, 2)   ; 123.46
Debug StrF(123.456, 2)   ; 123.46
Notice that string conversion functions correctly rounded 123.456 to 123.46, and did not simply truncate the value to 123.45.

Also, this is not a PureBasic issue, but an issue with binary-based arithmetics, occurring with all programming languages.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by mk-soft »

The representation of float and double are stored in structured form. Read up on WIKI
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 4123
Joined: Thu Apr 18, 2019 8:17 am

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by BarryG »

@eNano: Just use StrD() when displaying such numbers and it'll look as expected. Don't avoid PureBasic just because you might mistakenly think it can't show numbers correctly. (This also goes for any guests watching this topic and considering PureBasic).
eNano
User
User
Posts: 13
Joined: Wed Jun 05, 2024 4:48 pm

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by eNano »

Thanks for all the answers! I'm working with some imperial to metric unit conversions in purebasic, I was guessing this was some "binary kind of thing" that I don't understand. Is it ok if I keep working with float numbers and trust the results? will I loose too much accuracy if I do a couple of conversions between units? I just want to know if I'm doing this correctly. Thanks a lot
User avatar
jacdelad
Addict
Addict
Posts: 1992
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by jacdelad »

Depends von the range of numbers and precision you need. See help or Wikipedia.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by DarkDragon »

eNano wrote: Fri Aug 30, 2024 4:44 pm Thanks for all the answers! I'm working with some imperial to metric unit conversions in purebasic, I was guessing this was some "binary kind of thing" that I don't understand. Is it ok if I keep working with float numbers and trust the results? will I loose too much accuracy if I do a couple of conversions between units? I just want to know if I'm doing this correctly. Thanks a lot
It depends on the precision that you need and the range of values and the operations you use.

Integer binary numbers can be represented as b_0 * 2^0 + b_1 * 2^1 + b_2 * 2^2 + ... + b_(n-1) * 2^(n-1) where b_x are the bits and n is the amount of bits in that integer. Floating points are the same basically, with a shift in the exponent, so basically 2^c * (b_0 * 2^0 + b_1 * 2^1 + b_2 * 2^2 + ... + b_(n-1) * 2^(n-1)) where c is the shift (some implementation details left out for simplicity).

If you want to calculate with two numbers you often need to bring them to the same value for c first and that means cutting off at some point. Depending on their values that can mean a total loss for one of them.
bye,
Daniel
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by Fred »

If you need money like operation were all decimals needs to be perfect, double or float won't be enough. You need some special decimal libs like libmpec or use a language which has builtin support for decimals like C#
User avatar
Caronte3D
Addict
Addict
Posts: 1355
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by Caronte3D »

For maxim precision, a dedicate library is the better way for sure, anyway sometimes is enough something simple.
When I need to use money numbers I always use whole numbers this way:

Code: Select all

; Original value after some mathematical operation:
Define total.d = 54.9551111111111

total = total * 1000
Define total_rounded.d = Round(total * 0.1, #PB_Round_Up) * 0.01

; When need to show it:
Debug FormatNumber( total_rounded,2,".",",") ; result = 54.96
I don't know if #PB_Round_Up is correct for every country, but I think is ok for Euro zone.
BarryG
Addict
Addict
Posts: 4123
Joined: Thu Apr 18, 2019 8:17 am

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by BarryG »

@Fred: Maybe the "Debug" command should output numbers only in StrD() format (like in my example), so newbies won't get confused and post questions like this? Consider also: Someone trialing PureBasic might think it can't do math correctly and not buy it, just because they don't know about StrD() and the output of "Debug". ;)
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by AZJIO »

Previously, it seemed impossible to me (using Round()) to round to fractional parts, for example, from 54.6789 to get 54.68, but now I saw in FormatNumber() to specify an empty field to separate the whole part of FormatNumber(54.6789, 2, ",", "").
There should be links between the Round() and FormatNumber() pages in the help. They are in different sections, but they can help with the choice of function.

In decimal numbers 10/3=3.(3) It is also impossible to get an exact number if it is truncated to 20 characters. And multiplying inaccurate numbers will give artifacts in the extreme digits of the fractional part.

BarryG
I don't think it's necessary to round up the data for the sake of beginners. They will face this problem in almost any language. In AutoIt3, the author writes that he uses some functionality to fix (Int)

Code: Select all

Debug Int(0.7 + 0.2 + 0.1)
BarryG
Addict
Addict
Posts: 4123
Joined: Thu Apr 18, 2019 8:17 am

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by BarryG »

Fred wrote: Fri Aug 30, 2024 8:21 pmIf you need money like operation were all decimals needs to be perfect, double or float won't be enough. You need some special decimal libs like libmpec or use a language which has builtin support for decimals like C#
Nah, you can just use whole integers for the currency (to include the cents without floats) and then just insert a decimal point when needed for display. Lots of financial apps do that (I've even used them in government apps before). So for $100.21 + 3 cents, you'd do 10021+3 (to get 10024) but your app just displays it as "100.24" because the last two digits are always the cents.

Code: Select all

; Adding 3 cents to $100.21
Debug 100.21+0.03 ; 100.2399999999999948840923025
Debug 10021+003   ; 10024
User avatar
TI-994A
Addict
Addict
Posts: 2698
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by TI-994A »

BarryG wrote: Sat Aug 31, 2024 3:58 pm...you can just use whole integers for the currency (to include the cents without floats) and then just insert a decimal point when needed for display. ...
@BarryG: That's a fairly good approach, but it would still raise problems with multipliers and divisors, where the mantissa results would not always conform to the required decimal places. A simple loan scenario would entail amortisations and prorations, and would easily break this method.

In FINTECH, where transactions are voluminous, rounding of values is not always acceptable. They utilise highly specialised, purpose-built libraries to handle their calculations, factoring in every iota of variance. This is even more crucial in trading platforms.

However, for general financial applications like accounting or invoicing, simple rounding of floating point results, usually to two or four decimal places, is quite acceptable. Nevertheless, they would still be best stored as DECIMALS in databases, instead of floating point types. Even SQL faces the same inaccuracy issues.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
PBJim
Enthusiast
Enthusiast
Posts: 294
Joined: Fri Jan 19, 2024 11:56 pm

Re: Decimal point problem (was: Very noob doubt is driving me crazy)

Post by PBJim »

BarryG wrote: Sat Aug 31, 2024 3:58 pm
Fred wrote: Fri Aug 30, 2024 8:21 pmIf you need money like operation were all decimals needs to be perfect, double or float won't be enough. You need some special decimal libs like libmpec or use a language which has builtin support for decimals like C#
Nah, you can just use whole integers for the currency (to include the cents without floats) and then just insert a decimal point when needed for display.
If things were only that simple, Barry :D The solution you mention is fine for simple addition and subtraction, but it isn't as straightforward as that when we need to deal with fractions.

Code: Select all

PACKQTY=12             ; 12 in a pack
PACKPRICE=659          ; Price per pack $6.59

UNITPRICE.f = PACKPRICE / PACKQTY   ; Price per unit
Result, 54.9166679382

For floating-point, type .f, there are usually 7-digits of precision after which an error occurs. I could truncate after four decimal places and in this particular example it would be fine for my needs, but for larger values, that wouldn't be the case :

Code: Select all

PACKPRICE=6590000      ; Price per pack $65,900.00
Result, 549,166.6875

I've lost the precision I needed, even within just two decimal places, since the 7-digit precision was sufficient only up to the first decimal place. If I perform this on a non-PureBasic system, which is minicomputer database system I happen to be working on at this moment and which isn't based on floating-point arithmetic, I get a sensible value, currently set to four decimal places:

Result, 549,166.6666

In fact my desktop calculator gives me the same result. There was a comment on the forum I recall seeing, where a poster expressed difficulty obtaining accurate financial results in PureBasic and had performed them successfully within the database instead.
Post Reply