Raised This Month: $51 Target: $400
 12% 

Fix floating precision


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Xunfop
Member
Join Date: Mar 2012
Location: 97Club
Old 07-05-2014 , 03:27   Fix floating precision
Reply With Quote #1

As know IEEE 745 floating has precision problem, is it possible to integrate fix point from pawn?
Xunfop is offline
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
Old 07-05-2014 , 17:56   Re: Fix floating precision
Reply With Quote #2

I'm guessing that would require a huge amount of work to replace, if possible at all. So what is the problem with using it as is?
__________________
Black Rose is offline
Xunfop
Member
Join Date: Mar 2012
Location: 97Club
Old 07-06-2014 , 01:23   Re: Fix floating precision
Reply With Quote #3

For correct floating mathematical.
Xunfop is offline
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
Old 07-06-2014 , 01:37   Re: Fix floating precision
Reply With Quote #4

For what reason? It is pretty accurate as is.
Why would you need it more accurate?

You should probably give a good example if you expect anything done.

If you want to do an equal check on a value that is near you could just knock off some of the last couple of bits to make them irrelevant without deviating much from the original value. The best part being of course that it scales. Doesn't work as I expected.
__________________

Last edited by Black Rose; 07-06-2014 at 02:22.
Black Rose is offline
Xunfop
Member
Join Date: Mar 2012
Location: 97Club
Old 07-06-2014 , 02:27   Re: Fix floating precision
Reply With Quote #5

For kreedz time system, it count to 2nd decimal place, after it store the floating, the value goes wrong. It also make the mathematical value wrong.
Xunfop is offline
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
Old 07-06-2014 , 03:09   Re: Fix floating precision
Reply With Quote #6

You might see deviation at the 7th decimal (which isn't displayed by default). It may affect previous decimals if right on the edge. For example 0.1 might be 0.999999.
I don't know what Kreedz time system is but it sounds like a badly written plugin IMO.

Don't store values in float in any long time storage, round them to integers. If you want decimal points, multiply them by 100 first for 2 decimal points and divide them by 100 on load.
Same can be applied to strings. Turn them into strings and then shove a decimal point at the correct position.

Yes it's crude, but if we speak about efficiency it's completely trivial and won't matter at all unless you call it on every frame.

If you need a better answer than that, share the code.

Edit: Here are some examples of outputs using float_to_str() or a multiplied number used with num_to_str() with carefully placed decimal point at string level.
Both seems to work fine.
Code:
    new Float:test1 = -2.8;     new Float:test2 = -2.9 + 0.1;     server_print("%.2f", test1);     server_print("%.2f", test2);     new test3 = floatround(test1 * 100);     new test4 = floatround(test2 * 100);     new str1[32], str2[6];     new len = num_to_str(test3, str1, charsmax(str1));     str1[len + 1] = 0;     str1[len] = str1[len - 1]     str1[len - 1] = str1[len - 2]     str1[len - 2] = '.';     len = num_to_str(test4, str2, charsmax(str2));     if ( len < charsmax(str2) ) {         str2[len + 1] = 0;         str2[len] = str2[len - 1]         str2[len - 1] = str2[len - 2]         str2[len - 2] = '.';     }         server_print("%s", str1);     server_print("%s", str2);     new str3[32], str4[32];     float_to_str(test1, str3, charsmax(str3));     float_to_str(test2, str4, charsmax(str4));     new pos;     if ( ( pos = strfind(str3, ".") ) != -1 )         str3[pos + 3] = 0;     if ( ( pos = strfind(str4, ".") ) != -1 )         str4[pos + 3] = 0;     server_print("%s", str3);     server_print("%s", str4);

Code:
-2.79
-2.80
-2.80
-2.80
-2.80
-2.80
__________________

Last edited by Black Rose; 07-06-2014 at 03:29.
Black Rose is offline
fysiks
Veteran Member
Join Date: Sep 2007
Location: Flatland, USA
Old 07-06-2014 , 15:52   Re: Fix floating precision
Reply With Quote #7

Quote:
Originally Posted by Xunfop View Post
For kreedz time system, it count to 2nd decimal place, after it store the floating, the value goes wrong. It also make the mathematical value wrong.
You'll have to be more specific with how you are actually using these numbers. If you only need accuracy to the hundredths place then there is no issue with using floating point numbers because their accuracy is much much better than that. Like I said before, it is probably an issue with displaying only (which include writing it to a file in any non-binary form).
__________________
fysiks is offline
Xunfop
Member
Join Date: Mar 2012
Location: 97Club
Old 07-09-2014 , 06:48   Re: Fix floating precision
Reply With Quote #8

Here's the code.
PHP Code:
public fnLoadWorldRecord() {
    
g_bHasWR false;
    
    for(new 
0sizeof(g_sSaveDemosFile); i++) {
        if(!
g_bHasWR && file_exists(g_sSaveDemosFile[i])) {
            new 
hFile fopen(g_sSaveDemosFile[i], "r");
            new 
sData[96];
            
            while(!
feof(hFile)) {
                
fgets(hFilesDatacharsmax(sData));
                
                if(!
sData[0] || sData[0] == '^n' || equali(sDatag_sFirstDemosLine[i]) || !equali(sDatag_sMapNameg_iMapNameLen)) {
                    if(
g_bHasWR) {
                        break;
                    }
                    else {
                        continue;
                    }
                }
                
                new 
sMapName[64], sTime[10], sAuthor[32], sCountry[2];
                
                
trim(sData);
                
                if(
== 0) {
                    
parse(sDatasMapNamecharsmax(sMapName), sTimecharsmax(sTime), sAuthorcharsmax(sAuthor), sCountrycharsmax(sCountry));
                }
                else {
                    new 
sMapId[11], sTimeStamp[11], sAuthorId[11];
                    
                    
parse(sDatasMapNamecharsmax(sMapName), sTimecharsmax(sTime), sMapIdcharsmax(sMapId), sTimeStampcharsmax(sTimeStamp), sAuthorIdcharsmax(sAuthorId), sCountrycharsmax(sCountry), sAuthorcharsmax(sAuthor));
                }
                
                if(
sMapName[g_iMapNameLen] != '[' && g_iMapNameLen != strlen(sMapName)) {
                    if(
g_bHasWR) {
                        break;
                    }
                    else {
                        continue;
                    }
                }
                
                if(!
g_bHasWR) {
                    
g_bHasWR true;
                }
                
                if(
sMapName[g_iMapNameLen] == '[') {
                    if(
isdigit(sMapName[g_iMapNameLen 1])) {
                        
formatex(g_sWRExt[g_iWRAuthorsNum], charsmax(g_sWRExt[]), "[%s"sMapName[g_iMapNameLen 1]);
                    }
                    else {
                        
formatex(g_sWRExt[g_iWRAuthorsNum], charsmax(g_sWRExt[]), "[%c]"sMapName[g_iMapNameLen 1]);
                    }
                }
                
                
g_fWRTimes[g_iWRAuthorsNum] = str_to_float(sTime);
                
g_sWRAuthors[g_iWRAuthorsNum] = sAuthor;
                
                if(
g_iWRAuthorsNum >= 1) {
                    if((
g_fWRMinTime <= 0.0 && g_fWRTimes[g_iWRAuthorsNum] > 0.0) || 
                      (
0.0 g_fWRTimes[g_iWRAuthorsNum] < g_fWRMinTime)) {
                            
g_fWRMinTime g_fWRTimes[g_iWRAuthorsNum];
                    }
                }
                else {
                    
g_fWRMinTime g_fWRTimes[g_iWRAuthorsNum];
                }
                
                
g_iWRAuthorsNum++;
                
                continue;
            }
        }
    }
    
    if(
g_bHasWR) {
        
fnGenerateWRString();
    }
    
    return 
PLUGIN_HANDLED;
}

public 
fnGenerateWRString() {
    for(new 
0g_iWRAuthorsNumi++) {
        if(
0) {
            
add(g_sWorldRecordscharsmax(g_sWorldRecords), ", ");
        }
        
        new 
sWRTime[11];
        
        
fnConvertTime("float"g_fWRTimes[i], sWRTimecharsmax(sWRTime));
        
        
add(g_sWorldRecordscharsmax(g_sWorldRecords), g_sWRExt[i]);
        
        if(
equal(sWRTime"00:00.00")) {
            
add(g_sWorldRecordscharsmax(g_sWorldRecords), "^x03");
        }
        else {
            
add(g_sWorldRecordscharsmax(g_sWorldRecords), "^x04 ");
            
add(g_sWorldRecordscharsmax(g_sWorldRecords), sWRTime);
        }
        
        
add(g_sWorldRecordscharsmax(g_sWorldRecords), " ");
        
add(g_sWorldRecordscharsmax(g_sWorldRecords), g_sWRAuthors[i]);
        
add(g_sWorldRecordscharsmax(g_sWorldRecords), "^x01");
    }
    
    
g_sWorldRecords[160] = 0;
    
    return 
PLUGIN_HANDLED;
}

public 
fnConvertTime(type[], Float:timeconvert_time[], len) {
    new 
sTemp[11];
    new 
Float:fSeconds timeiMinutes;
    
    
iMinutes floatround(fSeconds 60floatround_floor);
    
fSeconds -= iMinutes 60;
    
    if(
equali(type"float")) {
        
formatex(sTempcharsmax(sTemp), "%02i:%05.2f"iMinutesfSeconds);
    }
    else {
        
formatex(sTempcharsmax(sTemp), "%02i:%02.0f"iMinutesfSeconds);
        
sTemp[strlen(sTemp) - 1] = 0;
    }
    
    
formatex(convert_timelensTemp);
    
    return 
PLUGIN_HANDLED;

Reading file format.
Quote:
8b1_brickngrass 231.68 Nukk ru 642
How to fix this with -0.01 problem?

And probably should move this thread to scripting help area?
Xunfop is offline
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
Old 07-10-2014 , 16:08   Re: Fix floating precision
Reply With Quote #9

You have to give some pointers or create some kind of function that I could test it with.
I don't really want to spend time creating a wrapper for this code just to try it out.
Sorry for being an asshole here but I don't know what you want and what the purpose of the code is.

Where exactly in the code is the problem. What value are you getting? What value do you expect?

If your problem is saving to/reading from a file with 2 decimals, save with 3 decimals or more. Every time you save without preformatting the float, you risk it being off by .01 when you save with two decimals. 3 decimals: .001 and so on...
__________________

Last edited by Black Rose; 07-10-2014 at 16:15.
Black Rose is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 07-11-2014 , 11:46   Re: Fix floating precision
Reply With Quote #10

Quote:
Originally Posted by Black Rose View Post
I'm guessing that would require a huge amount of work to replace, if possible at all. So what is the problem with using it as is?
I imagine it would since AMX and SM both just wrap the Pawn Floating Point Support Library (PDF).

In fact, I don't know enough about infinite precision math libs to know if they'd be feasible in Pawn.

Having said that, you can fake it by using cells with whole values and just displaying them as if they were decimals. Maybe using 16 bits as the fractional part and 16 bits as the whole part? (One of them would have to include the sign bit, though)
__________________
Not currently working on SourceMod plugin development.

Last edited by Powerlord; 07-11-2014 at 11:49.
Powerlord is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 00:39.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode