Page 1 of 2

Decimal numbers problem

Posted: Tue Jun 02, 2015 6:53 am
by emar101
Hello I'm new in using purebasic. I have this problem that everytime i get input from a string gadget and convert it to double, say the input is 12.34 it will become 12.33999999999 and so on. Is there a way to retain the input as is (12.34)? Thank you for the upcoming answers. :D

Re: Decimal numbers problem

Posted: Tue Jun 02, 2015 7:50 am
by Shield
No, there is not. The only way to keep the original number is storing it as a string.
Whenever you convert to double you'll have a loss of precision due to the way floating point
numbers work. That's not a bug but is to be expected. :)

Re: Decimal numbers problem

Posted: Tue Jun 02, 2015 9:55 am
by emar101
Thank you Shield. However, do you know a procedure or a routine that i can use in order for me to use the exact number in an operation rather than the converted number? :D

Re: Decimal numbers problem

Posted: Tue Jun 02, 2015 10:46 am
by Shield
PB doesn't offer anything like this natively, but you might want to have a look at GMP:
http://www.purebasic.fr/english/viewtop ... 12&t=61315

If you'd tell us what exactly you intend to do we might be able to come up with better solutions.

Re: Decimal numbers problem

Posted: Tue Jun 02, 2015 11:09 am
by infratec
Hi,

I think you did not understand what happens:

12.34 results always in any calculation to 12.33999999.
It doesn't matter if you store it up to the calculation as string or not.
When you use it for calculation it is again 12.339999.

So it's only for your display and the user and for that you can use StrF(floatnumber, 2)

But don't think that's a bug from PB.
All other languages does the same. Maybe some of them lie to you and show already a 'rounded' value.
But latest when they calculate with it ... 12.339999

You can only use .d instead of .f which can store more exactly.

Bernd

Re: Decimal numbers problem

Posted: Tue Jun 02, 2015 11:27 am
by Josh
If you have always two digits after decimal point, use a long/integer/quad and store the value multiplied with the factor of 100.

Re: Decimal numbers problem

Posted: Wed Jun 03, 2015 9:17 am
by captain_skank
Not looking to cause an argument, but PB SHOULD fix the result for you.

Code: Select all

Debug 1.4 + 1.4
results in 2.7999999999999998 which is wrong

The answer is quite clearly 2.8

How PB, the OS or the processor handle numbers internally is irrelevant as it needs to return the correct value.

Just my two cents

Re: Decimal numbers problem

Posted: Wed Jun 03, 2015 9:42 am
by Shield
It's only wrong in a mathematical sense. The result is as close as you can get with floats.
It has nothing to do with PB, it has to do with the way floating point numbers are stored and handled.
The reason you get this weird number is that it's impossible to express 2.8 as a binary float.

It's not a bug, it's just how it is. Floats are designed to be fast and provide a good approximation.
There are numerous libraries designed specifically for the exact calculation of large numbers.

Re: Decimal numbers problem

Posted: Wed Jun 03, 2015 9:51 am
by Danilo

Re: Decimal numbers problem

Posted: Wed Jun 03, 2015 9:52 am
by Dude
captain_skank wrote:Debug 1.4 + 1.4
The answer is quite clearly 2.8

Code: Select all

num.d = 1.4 + 1.4
Debug StrD(num)
Sure is! ;)

Re: Decimal numbers problem

Posted: Fri Oct 02, 2015 11:16 am
by SeregaZ
so have you any solution about it? it not want to make correct round:

Code: Select all

Procedure.d countstr(tmp$)
  
  ReplaceString(tmp$, ",", ".", #PB_String_InPlace)
  tmp.d = ValD(tmp$)
  
  ProcedureReturn tmp
EndProcedure

Procedure countstrdebug(x$, y$)
  
  Debug countstr(x$) * countstr(y$)
  Debug StrD(countstr(x$) * countstr(y$), 5)
  Debug StrD(countstr(x$) * countstr(y$), 4)
  Debug StrD(countstr(x$) * countstr(y$), 3)
  Debug StrD(countstr(x$) * countstr(y$), 2)

EndProcedure

countstrdebug("53695,5", "3,27")

Debug ""

countstrdebug("12067,5", "3,27")
first time work fine, but second is suks... 39460.725 must come to 39460.73 - but it is 39460.72 hrrrrrrrrrrrrrrr...

Re: Decimal numbers problem

Posted: Fri Oct 02, 2015 11:30 am
by Keya
btw SeregaZ your "," to "." StringReplace looks like the type that could use #PB_String_InPlace for a speed gain

Re: Decimal numbers problem

Posted: Fri Oct 02, 2015 11:50 am
by SeregaZ
i am obey and fix it :) but anyway need to a little help with that.

i'll need to get all digits, what lay far than 2 symbols? and check it one by one?
39460.72499 - get 499 as val, then use some like this: StrD(499/10, 0) in repite until it will get only 1 digit and check it 0-4 or 5-9?

Re: Decimal numbers problem

Posted: Fri Oct 02, 2015 12:54 pm
by SeregaZ
some like this?

Code: Select all

tmp$ = "12345.124444449"
;tmp$ = "12345.12"
;tmp$ = "12345.123"

tmp = FindString(tmp$, ".")
If tmp And Len(tmp$) - tmp > 2
  
  cuttmp$ = Right(tmp$, Len(tmp$) - tmp - 2)
  cuttmp = Val(cuttmp$)
  
  Debug cuttmp
  Debug cuttmp$
  
  If Len(cuttmp$) > 1
    Repeat
    
      If Val(Right(cuttmp$, 1)) > 4
        cuttmp$ = StrD(cuttmp/10, 0)
      Else
        cuttmp$ = Left(cuttmp$, Len(cuttmp$)-1)
      EndIf
    
      cuttmp = Val(cuttmp$)
 
    Until Len(cuttmp$) < 2

  EndIf

  Debug cuttmp$
  
  tmp$ = Left(tmp$, tmp+2)
  
  If Val(cuttmp$) > 4 
    tmp$ = ReplaceString(tmp$, ".", "")
    tmp$ = Str(Val(tmp$)+1)
    tmp$ = Left(tmp$, Len(tmp$)-2) + "." + Right(tmp$, 2)
  EndIf  
  
EndIf

Debug tmp$
maybe someone know more ellegant solution?

Re: Decimal numbers problem

Posted: Fri Oct 02, 2015 1:35 pm
by Paul
This procedure has served me well. I think it came from Danilo back in the day?

Code: Select all

Procedure.s Float(number.f)
  places.l=2
  vf.f=number*Pow(10,places)
  vs.s=Str(vf)
  rs.s=Left(vs,Len(vs)-places)+"."+Right(vs,places)
  If rs=".00" Or rs=".0"
    rs="0"
  EndIf
  ProcedureReturn rs
EndProcedure


Debug float(1.4+1.4)