Author Topic: Seeking advice: Correctly handling float values  (Read 299 times)

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« on: July 15, 2012, 09:47:27 pm »


               Hi,

Considering the rather well known precision problems with floats, what is the best approach to at least reduce the impact, for instance in such a situation:

float fData = StringToFloat(Get2DAString());

I'm currently using this for a custom IP system(calculating cost), and the retrieved values are float, for the most part, unfortunately. So, if the 2DA value is 0.9, I display its value right after assignment, and I get 0.8999999 with maybe a few more or less 9, 50 being the last two numbers of the decimal part. No big deal with small numbers but for big ones, ouch...

Would there be a way around this problem?

Thanks!

Kato 
               
               

               


                     Modifié par Kato_Yang, 15 juillet 2012 - 08:54 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #1 on: July 15, 2012, 09:55:50 pm »


               you could probably convert the strint to int on your own and multiply it by 10 or 100 in order to get integer. Then in the cost formula you simply divite it with 10 or 100 again.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #2 on: July 15, 2012, 10:09:55 pm »


               Umm,  Why do you need a way around this Problem?  

Is it really a problem?
               
               

               
            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #3 on: July 15, 2012, 10:14:59 pm »


               

Lightfoot8 wrote...

Umm,  Why do you need a way around this Problem?  

Is it really a problem?


Well, the final IP cost is not exactly what it should, although the formula I'm using works very well, so it's kind of frustrating lol.

Kato
               
               

               
            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #4 on: July 15, 2012, 10:23:27 pm »


               

ShaDoOoW wrote...

you could probably convert the strint to int on your own and multiply it by 10 or 100 in order to get integer. Then in the cost formula you simply divite it with 10 or 100 again.


Yep, I might try this, ty ShaDoOoW.

Kato 
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #5 on: July 15, 2012, 10:52:05 pm »


               How far off is the number.  And how much precision are you looking for.   For example would FloatToString(fValue,18,3) return the value you are looking for
               
               

               
            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #6 on: July 15, 2012, 11:00:32 pm »


               

Lightfoot8 wrote...

How far off is the number.  And how much precision are you looking for.   For example would FloatToString(fValue,18,3) return the value you are looking for


I guess it would be ok to at least start from the correct 2DA values, but since I'm not sure yet:

// Returns the same property cost as if upgrading oItem with ip in the toolset
float GetIPCost(object oItem, itemproperty ip)
{
   int nProp = GetItemPropertyType(ip);
   int nItemType = GetBaseItemType(oItem);
   float fPropCost = StringToFloat(Get2DAString("ItemPropDef", "Cost", nProp));
   float fItemMult = StringToFloat(Get2DAString("baseitems", "ItemMultiplier", nItemType));
   float fCostTableCost = 1.0;
   int nCostTable = GetItemPropertyCostTable(ip);
   if(nCostTable > -1)
   {
      string sCostTable = Get2DAString("iprp_costtable", "Name", nCostTable);
      fCostTableCost = StringToFloat(Get2DAString(sCostTable, "Cost", GetItemPropertyCostTableValue(ip)));
   }
   return 1000.0 * fItemMult * pow(fPropCost, 2.0) * pow(fCostTableCost, 2.0);
}

EDIT: This function is currently used with another which takes care of the item's cost itself. The latter simply needs to add all the prop costs + the item's base cost + the additional cost = The new item's cost, same as in the toolset, provided that the 2DA values are passed correctly.


Kato
               
               

               


                     Modifié par Kato_Yang, 16 juillet 2012 - 12:37 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #7 on: July 16, 2012, 02:22:06 am »


               Well For one, unless I am missing something,  it looks like your  formula is way off. 

The formula for Item price is :


ItemCost = [BaseCost + 1000*(Multiplier^2 - NegMultiplier^2) + SpellCosts]*MaxStack*BaseMult +AdditionalCost

Where the  multiplyer is the sum of all of the postive  "ItemPropertyCost's" modifiersand the  NegMultiplier is the sum of all of the negtive ItemPropertyCost's for all the item props on the item.

Where each
ItemPropertyCost = PropertyCost + SubtypeCost + CostValue;
               
               

               


                     Modifié par Lightfoot8, 16 juillet 2012 - 01:28 .
                     
                  


            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #8 on: July 16, 2012, 04:40:35 am »


               Yes, ty L8, but out of curiosity, do you get the same cost as in the toolset with the formula? Maybe I'm doing something wrong:

For example, Dagger +1 enhancement would mean:
2 + 1000*pow(1.0 + 0.0 + 0.9, 2)*1*2 = 7222, obviously not correct, but multiplying the costs instead of adding them seems to work:
2 + 1000*pow(1.0 * 0.9, 2)*1*2 = 1622, the toolset cost. (the subtype is not used here because the property cost is not 0 and the prop has none anyway). So I'm a bit confused with the formula...

Kato
               
               

               


                     Modifié par Kato_Yang, 16 juillet 2012 - 03:55 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #9 on: July 16, 2012, 07:02:07 am »


               Well now Im confused also:   I also came up with the same results you did.   So it looks like it is using the formula as stated for the spell cost.  

That one is:

CastSpellCost = (PropertyCost + CostValue)* SubtypeCost

I do not have time to test everything out right now.   Who know perhaps it was a misprint and they inverted the SpellCost and iProp  formulas.   Or perhaps it is a bug and they are using the castSpellCost function for both.  

I may get some more time to look into it later this week.
               
               

               
            

Legacy_Kato -

  • Hero Member
  • *****
  • Posts: 747
  • Karma: +0/-0
Seeking advice: Correctly handling float values
« Reply #10 on: July 16, 2012, 09:02:07 pm »


               Well, I have tested a lot of props multiplying the costs instead of adding them, the returned cost is always the same as in the toolset, and it even looks like the float precision is not a problem anymore, strangely. So the initial function becomes:

float GetIPCost(itemproperty ip)
{
    int nProp = GetItemPropertyType(ip);
    int nSub = GetItemPropertySubType(ip);
    int nCostTable = GetItemPropertyCostTable(ip);
    float fPropCost = StringToFloat(Get2DAString("ItemPropDef", "Cost", nProp));
    float fSubCost = 1.0;
    float fCostValue = 1.0;
    if(fPropCost == 0.0 && nSub > -1)
    {
       string sSubTable = Get2DAString("ItemPropDef", "SubTypeResRef", nProp);
       fSubCost = StringToFloat(Get2DAString(sSubTable, "Cost", nSub));
    }
    if(nCostTable > 0)
    {
       string sCostTable = Get2DAString("iprp_costtable", "Name", nCostTable);
       fCostValue = StringToFloat(Get2DAString(sCostTable, "Cost", GetItemPropertyCostTableValue(ip)));
    }
    return fPropCost * fSubCost * fCostValue;
}
 
The negative prop costs are not included because they do not affect item value, at least in the toolset. Also, this only returns the total cost of a single prop, the final formula is applied in another function handling the item cost itself, in my case, and the final item cost always seems correct.

Thanks a lot for the help!

Kato 
               
               

               


                     Modifié par Kato_Yang, 16 juillet 2012 - 08:18 .