Super Newbie questions!
BlitzMax Forums/BlitzMax Beginners Area/Super Newbie questions!
| ||
Hi, This is the first piece of code I wrote in BMax, it's supposed to read a preference txt file which contains settings: -------------------------------------------------------------------------------------------- Strict Global SettingsFile$ = "test.txt" Global User_Credits%, Base_Points%, Talent_Amount#, ReGen_Cost%, Break_Min#, Break_Max#, Traits_Total% ' Global file:TStream = ReadFile(SettingsFile) If Not file RuntimeError "could not open file " + SettingsFile While Not Eof(file) Local CurrentLine$ = ReadLine(file) 'Reads a line from the file 'Local Label$ 'How come the code didn't work (No error message) if I decleared label here instead of inside the loop? If CurrentLine [0..1] <> "'" Then Local BeginPos = CurrentLine.Find(":")+1 'Find the : mark then increase the postition by 1 Local Label$ = CurrentLine [0..CurrentLine.Find(":")] 'Cut the string from the start of the string til the ':' character, not including the ':' Select Label Case "User Credits" User_Credits = Int CurrentLine[BeginPos..CurrentLine.Length] Case "Base Points" Base_Points = Int CurrentLine[BeginPos..CurrentLine.Length] Case "Talent Amount" Talent_Amount = Float CurrentLine[BeginPos..CurrentLine.Length] Case "ReGen Cost" ReGen_Cost = Int CurrentLine[BeginPos..CurrentLine.Length] Case "Break Min" Break_Min = Float CurrentLine[BeginPos..CurrentLine.Length] Case "Break Max" Break_Max = Float CurrentLine[BeginPos..CurrentLine.Length] Case "Traits Total" Traits_Total = Int CurrentLine[BeginPos..CurrentLine.Length] End Select End If Wend Print User_Credits Print Base_Points Print Talent_Amount Print ReGen_Cost Print Break_Min Print Break_Max Print Traits_Total CloseStream file -------------------------------------------------------------------------------------------- The settings file is like this: 'Test Settings file User Credits: 10000 Base Points: 150 Talent Amount: .15 ReGen Cost: 200 Break Min: .45 Break Max: .55 Traits Total: 9 My question is: 1. Why all three float numbers end up having not quite accurate values, for example Break_Min, instead of .45, it got 0.449999988 2. how do I round numbers to two decimals? In VBA I'd use ROUND but I think it's something different in Bmax? 3. There are better ways to do this right? I'm no programmer at all, have only been doing VBA scripts for 2 weeks and bought Bmax just yesterday, so please go easy on me ;D I'm a game artist, been doing that for many years, but want to get into actually design some games myself hahaha, dunno if I could ever do that, being able to illustrate my ideas with code would be cool in enough! Thanks! |
| ||
1. Because floats are not precise enough, you need to use double for more accurate values. 2. There is no function for that. The simplest way might be function round:string(value:double,digit:int) ' return type must be string otherwise it will have more than 2 digit value :* (10:double)^digit local valuei:int = int(value) local result:string = string(valuei) result = left(result, result.length - digit) + "." + right(result,digit) return result end function 3. Better is a thing of definition. You could use some kind of an ini file and parsing, would perhaps be cleaner. Or if you know the order in which the data are in the file, you can simply assign them. (I do that with my language file, only the content, no key names in front etc. Allows straight reading into a string reference) |
| ||
check out maXML module, think you'll find a link on module tweeks forum, idea for config files make things real easy from the programming point of view |
| ||
Hi thanks for the quick response! I just tried double, still got a long number. I'll try to use your function.. but hmm I don't understand what you are doing in there so will probably take me a while ;0 thanks again.. |
| ||
What Dreamora was aiming for was:Function round:String(value:Double,digit:Int) ' return type must be string otherwise it will have more than 2 digit ' value = the number you want to be rounded. ' digit = the number of digits to round to. value :* 10!^digit ' so, if value = 0.45 and digit = 2, value will now be 0.45*100 = 45 Local valuei:Int = Int(value) ' Converts 'value' to an integer. Local result:String = String(valuei) ' 'result' is now a string containing "45" result = Left(result , result.length - digit) + "." + Right(result , digit) ' this just formats the string to display the correct decimal value. Return result End Function Print round(.45!,2) Make sure you feed the function a double (put a ! on the end of the values you send it, or make sure you use a variable of type double). There's a better way of doing this, I'm sure. |
| ||
oops yeah my stupidness, pressed * instead of ^. corrected that. |
| ||
A better way:Function round2:String(value:Double , digit:Byte) Local result:String = String(value) result = Left(result , digit + Instr(result , "." , 1) ) If digit = 0 result = Left(result , Len(result) - 1) EndIf Return result End Function Print round2(.45! , 2) Print round2(10! , 2) Print round2(15.3333! , 2) Print round2(2.2! , 5) Print round2(1234.5678!,1) Print round2(99.99!,0) This will always round down, so round2(55.59,1) will yield "55.5". |
| ||
There is a problem with that: Different language versions of Windows have different handling for the digit point which is why this will fail. (you could use a replace(result,",",".") before the result = left thought) |
| ||
Good point, I didn't even think of that. Thanks Dreamora :) |