• (disco)

    I think the Dev should get a +1

    There are times when you have to do stuff like this. Once upon a time there was a certain version of a certain programming language that was used for a multi-currency e-commerce site.

    A User (as in somebody paying to use the very customised Product) complained that a certain price was wrong.

    Long story short: Certain numbers when rounded and forced into 2 decimal places for the proposes of VAT calculation got the rounding "wrong".

    In the end the Dev "found" all these wrong numbers, and built a special function to deal with them. A function that would, out of context be a considerable :wtf:

    Incidentally, and not related to this story, the Dev concerned would comment his code with the phrase "This is not a WTF" when required.

  • (disco) in reply to loose

    You shouldn't use floats (of any precision) to deal with currency amounts. You should use decimals instead (or do fixed-point with integers), so exact decimal amounts do not become approached binary amounts and you can implement the rounding rules relevant to your application.

  • (disco)
    higher precision **then** a float

    Somehow this is what I zeroed in on.

  • (disco) in reply to loose
    loose:
    A function that would, out of context be a considerable

    in context it's a pretty good :wtf: too,

    worse actually because you should not use floats or doubles for currency.

    Repeat after me:

    #The only correct type for currency is decimal. Any other type will cause trouble in the future.

    and that included integer types, because you will eventually have to change your precision and you can't do that sanely with integer stored decimals.

  • (disco) in reply to Dogsworth
    Dogsworth:
    this is what I zeroed0.000000000014634ed in on.

    FTFY

  • (disco) in reply to Khudzlin
    Khudzlin:
    You shouldn't use floats (of any precision) to deal with currency amounts.

    My point wasn't about using floats or not. It was about rounding. Most system either round up or round down when confronted with the dreaded 0.5 of a penny, or 0.005 of a £. What happened here and I must stress these are pure examples, was certain numbers like 12.375 would round down to 12.37 rather than the expected round up to 12.38

    When you are dicking about with e-commerce, minimum box / pallet quantities, VAT Inc / VAT Exc prices. And the Customer wants £13.99inc VAT price, from his given exc VAT price. You need to get it right. Not only that, you would be surprised just how many customers bitch about getting overcharged by a penny. Or the loss of trust that such errors engender in your website.

    But you are right, if you have decimal / currency type numbers you should use them. Or, as I do in a loosely type language multiply by 100, do everything as INT Math, and divide by 100. However, VAT is a whole new world of HELL

    In connection with the Article: I was just saying, at least the Dev did explain, and maybe he had a reason for doing it that way

  • (disco) in reply to accalia
    accalia:
    The only correct type for currency is decimal
    loose:
    My point wasn't about using floats or not. It was about rounding. Most system either round up or round down when confronted with the dreaded 0.5 of a penny, or 0.005 of a £. What happened here *and I must stress these are pure examples*, was certain numbers like 12.375 would round down to 12.37 rather than the expected round up to 12.38

    When you are dicking about with e-commerce, minimum box / pallet quantities, VAT Inc / VAT Exc prices. And the Customer wants £13.99inc VAT price, from his given exc VAT price. You need to get it right. Not only that, you would be surprised just how many customers bitch about getting overcharged by a penny. Or the loss of trust that such errors engender in your website.

    But you are right, if you have decimal / currency type numbers you should use them. Or, as I do in a loosely type language multiply by 100, do everything as INT Math, and divide by 100. However, VAT is a whole new world of HELL

    In connection with the Article: I was just saying, at least the Dev did explain, and maybe he had a reason for doing it that way

    CBA to type all that in again :stuck_out_tongue:

  • (disco) in reply to loose
    loose:
    My point wasn't about using floats or not

    And my point was a naieve reading of your post would seem to have you asserting, or at least accepting, that Double is an acceptable data type for currency. It is not, so for clarity I "corrected*" your post.

    *posted a post of my own with the "correction"

  • (disco) in reply to accalia
    accalia:
    naieve reading

    I will have none of this sort of behaviour with my posts. :laughing: :manically:

    But you response is appreciated. But I do have to point this little gem out: loosely typed language - Afterthought :hanzo: edit

  • (disco) in reply to loose
    loose:
    But you response is appreciated.
    Pinging @accalia because why not.
  • (disco)

    Accurate? Accurate? String conversion of floats is not accurate.

    It's precise. I give you that. So they should have written

     * @param precise
     * Flag to specify whether to use a precise conversion from float to double
     * Precise means strings will be used what may result in a bit slower 
     * performance. Not precise means typecasting will be used which is accurate (and precise).
    

    What could they mean by "this result in a fault since a double has a higher precision than a float."? How could this conversion possibly result in a fault? WTF language is this?

  • (disco) in reply to loose

    The thing is you cannot expect floats to work, because an exact decimal amount will be rounded in binary (12.375 happens to be exact in binary - the fractional part is 3/8 - but it's the exception rather than the rule). To achieve correct rounding, you need to start from an exact amount instead of one that is already rounded in a way you cannot control (which is what happens with binary floating point).

  • (disco)

    Has anybody noticed the other :wtf: in the original code?

    The control flag (seriously, dude, control coupled? Constantine and Yourdon would have kittens!) is badly named, regardless of any of the disvirtues of the types chosen.

    The name is accurate, but should really be normalised - the via-string conversion will have a specific effect on the not-exactly-representable value of e.g. 4.70 when seen in the lens of the higher precision value, that a naked cast does not (zero-fill is quite likely for the result of the cast, and it certainly won't be the same as doing the to-double conversion on the string).

    And indeed, I don't see what kind of fault one could get from a precision-boosting conversion.

  • (disco) in reply to gleemonk
    gleemonk:
    Accurate? Accurate? String conversion of floats is not accurate.

    It's precise. I give you that.

    Yup. Time to dig this out again it seems:

    http://cdn.antarcticglaciers.org/wp-content/uploads/2013/11/precision_accuracy.png

    gleemonk:
    What could they mean by "this result in a fault since a double has a higher precision than a float."?

    A compiler warning perhaps? The comment comes across as ESL.

    Though the warnings are normally when possible truncation happens going from double to (single) float (though I did find this printf() error on some obscure platform.)

  • (disco) in reply to loose
    loose:
    I think the Dev should get a +1

    Maybe, but the dev ought to also get a slap upside the head for the quantity of magical thinking involved in that code. Rounding might be important sometimes, but going from float to double via a string is not a winning proposition, especially as the precision of the conversion to string isn't specified.

    Also, most float-to-string conversion code is awful anyway. Because doing it right is hard

  • (disco) in reply to PJH
    PJH:
    A compiler warning perhaps?

    It's Java. I think that widens transparently.

  • (disco) in reply to Khudzlin
    Khudzlin:
    12.375

    As quantified in my post, this was a purely random number on my part. As it happens there is a whole argument about something very similar HERE, which actually cites £14.375 (not bad for a 7+ year recall although I did get the Up / Down bit wrong. But Meh! who ever worries about that, it's consistency that counts.), and strangely enough the calculation involves multiplying by 1.15 (15% VAT at that time).

    For the record, this e-commerce site was tied in to the Accounts data / prices etc so the books had to balance as well. There are some horrors you do not want to visit you, a HMRC VAT inspection ranks pretty high on that list.

    I will see, if the Dev still has the hack he used to find the "wrong" numbers

  • (disco) in reply to loose
    loose:
    In connection with the Article: I was just saying, at least the Dev did explain, and maybe he had a reason for doing it that way

    ...sniff..

  • (disco) in reply to loose

    Let's take your example. 12.5 is exact in binary, but 1.15 is not (it happens to be rounded down using both floats and doubles, according to the IEEE 754 specification), so you do not get 14.375 when multiplying them, but a slightly lower number, which will then round to 14.37 instead of the 14.38 you expect (and is mandated by HRMC VAT if I understand correctly).

    Using decimals, both 12.5 and 1.15 are exact, so the product is exactly 14.375, which then rounds to 14.38 according to the rules set by HRMC VAT.

  • (disco) in reply to loose
    loose:
    Long story short: Certain numbers when rounded and forced into 2 decimal places for the proposes of VAT calculation got the rounding "wrong".

    This is a long time ago now but when doing this stuff I understood that owing to the needs of multicurrency triangulation, currencies within the EU should always be handled to 3dp for consistent results. (Except for the lira, which at the time was several thousand to the Euro and so could be conveniently handled with no dp at all.) There was a lot of argument at the time about whether, when buying n items at price x, the VAT should be calculated as (VAT on x)*n, or VAT on (nx).

  • (disco) in reply to accalia

    Or in this case, BigDecimal since Java doesn't have a built-in decimal type.

  • (disco) in reply to powerlord

    .... right, because Java isn't a big enough :wtf: on its own....

    yes, if there is no native time third party alternatives are acceptable.

  • (disco) in reply to Khudzlin
    Khudzlin:
    Using decimals, both 12.5 and 1.15 are exact, so the product is exactly 14.375, which then rounds to 14.38 according to the rules set by HRMC VAT.

    fuck this pissant editor ##YES! ABSOLUTELY!| TOTALLY! COULD NOT AGREE WITH YOU MORE!!!!!!!!!!!!!!!! But for some numbers it would unexpectedly round in the OTHER direction.

    To save you a mouse click (If it is Too Lond and you Don't want to Read, please look at the highlighted / broken format section about a 1/3 of the way through. Taking a special note of the previous poster's parting shot.

    AGAIN I am not claiming that this was the case as in that I described, but very similar.

    [2006-01-14 05:15 UTC] adi at rogers dot com Description:

    Very lame/unreliable ;) Both round() and number_format() succumb to this problem. They cannot handle float or double variables properly even though those variable types are "flawed / limited" as apparently described numerous times on here by PHP personnel. Well my code below appears to showcase the bug which will hopefully not be shot off as "bogus" like many times before as reported in the past by various people.

    I found a work-around which I will now be using. Convert your value to a string variable before passing it to the round() or number_format() function.

    Reproduce code:

    $num=12.5*1.15; // Produces 14.375 as type: double. $num_same_thing=14.375; // Produces 14.375 as type: double. echo "Wrong: ".round($num, 2)."\r\n"; echo "Wrong: ".number_format($num, 2)."\r\n"; echo "'Magically' correct: ".round($num_same_thing, 2)."\r\n"; echo "'Magically' correct: ".number_format($num_same_thing, 2)."\r\n"; // The above two variables are the same value and same type, yet are rounded differently. settype($num, "string"); // Now that $num is a string, we get the right result. echo "Converted to string and is now correct: ".round($num, 2)."\r\n"; echo "Converted to string and is now correct: ".number_format($num, 2)."\r\n";

    Expected result:

    The functions should have outputted 14.38 no matter how the variables of type 'double' were assigned the value 14.375.

    Patches

    Add a Patch

    Pull Requests

    Add a Pull Request

    History

    All

    Comments

    Changes

    Git/SVN commits

    Related reports

    [2006-01-14 11:16 UTC] [email protected] Output on my machine using default precision 12: Wrong: 14.38 Wrong: 14.38 'Magically' correct: 14.38 'Magically' correct: 14.38 Converted to string and is now correct: 14.38 Converted to string and is now correct: 14.38

    And it works exactly like it's supposed to. round() rounds up to 2 decimals. Same goes for number_format().

    14.375 == 14.38 but 14.374 == 14.37

    There is no bug here, and please, don't bother reopening this yet again.

    > [2006-01-14 15:55 UTC] adi at rogers dot com I just confirmed this issue to still exist on the following systems:

    > Windows XP Pro SP2 [IIS 5.1 ISAPI] (PHP 5.1.2 / php.ini precision: 12) > Windows XP Pro SP2 [IIS 5.1 CGI] (PHP 5.1.0RC1 / php.ini precision: 12) > Windows Server 2003 Enterprise x64 Edition SP1 [IIS 6.0 CGI] (PHP 5.1.2 / php.ini precision: 12)

    > PHP was installed on all three systems manually (not using the installer).

    > Hope that helps in isolating this issue.

    [2006-01-14 16:06 UTC] [email protected] What EXACTLY is the output when you set precision to 32?

    [2006-01-15 06:34 UTC] adi at rogers dot com As requested, the exact output with 32 as the precision:

    Wrong: 14.369999999999999 Wrong: 14.37 'Magically' correct: 14.380000000000001 'Magically' correct: 14.38 Converted to string and is now correct: 14.369999999999999 Converted to string and is now correct: 14.37

    [2006-01-15 06:40 UTC] adi at rogers dot com Oh, and as I had suspected, here is the value of $num with 32 precision: 14.374999999999998 With 12 as the precision, it is: 14.375

    [2006-06-14 15:50 UTC] [email protected] Please try using this CVS snapshot:

    http://snaps.php.net/php5.2-latest.tar.gz

    For Windows:

    http://snaps.php.net/win32/php5.2-win32-latest.zip

    [2006-06-14 22:11 UTC] adi at rogers dot com Regretfully, the same output:

    5.2.0-dev

    Wrong: 14.37 Wrong: 14.37 'Magically' correct: 14.38 'Magically' correct: 14.38 Converted to string and is now correct: 14.38 Converted to string and is now correct: 14.38

    The 32 precision results are also the same [as the ones on January 15].

    [2006-10-10 07:45 UTC] troy20 at mail dot ru Code: for ($i = 1.075;$i <= 1.975;$i=$i+0.1) {echo round($i,2);} Result: 1.08, 1.18, 1.28, 1.38.... But if echo round(1.275,2); echo round(1.275*100); we have 1.27 and 127.

    Another "same" example: for ($i = 1.075;$i <= 20.975;$i=$i+0.1) {echo round($i,2);}

    Win2003 + Apache 2.0.59 + php 5.1.6

    [2006-10-10 21:44 UTC] adi at rogers dot com Amen to that ;)

    [2006-10-30 13:30 UTC] dave at koales dot co dot uk I think this is a Windows vs others thing. I have the same rounding error using PHP 5.0.5 on Windows XP SP2.

    The same problem does not exist on my webhost, who use PHP 4.3.9 and Redhat Linux (need any more detail).

    The code I used was:

    echo "Correct VAT = " . round( 0.525, 2 ) . "\r\n"; echo "Wrong VAT = " . round( 3 * ( 17.5 / 100.0 ), 2 ) . "\r\n";

    Outputs 0.53 for each on webhost (under Linux) and 0.52 for the second test under Windows (0.53 for the first test).

    I've also had very bizarre rounding errors with MySQL. The rounding error came and went depending on how the calculation was constructed!

    [2006-10-31 00:39 UTC] adi at rogers dot com Aww well it's too late for me to bug it for Windows Vista as we've entered Release Candidate 2 :( I'll test this again on IIS7 with the final version of Vista...

    [2007-01-07 04:07 UTC] [email protected] Please try using this CVS snapshot:

    http://snaps.php.net/php5.2-latest.tar.gz

    For Windows:

    http://snaps.php.net/win32/php5.2-win32-latest.zip

    [2007-01-09 02:56 UTC] terrychangsharp at gmail dot com I tested the code on PC + FreeBSD 6.1 + Apache 2.2.3 + PHP 5.2.0 and get the same results. Actually, the seemingly coincident numbers $num and $num_same_thing are in fact not the same thing: $num - $num_same_thing yields -1.7763568394003E-015, not zero, so $num is smaller than 14.375 and round($num) is 14.37, not 14.38. Thus this "bug" is more like a floating point error thing, not a real bug.

    [2007-01-15 01:00 UTC] php-bugs at lists dot php dot net No feedback was provided for this bug for over a week, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".

    [2007-03-16 15:36 UTC] me at nospam dot com I don't have a simpler test case, but in doing more testing, I found that the rounding apparently just doesn't work. When you print out a number that was rounded, it will appear correctly, but when you try to do math functions with other similar numbers (ie 6.08 - 6.08), I will get a remainder of like 2.039283e-16. However, setting the type to each variable as a string made it work correctly.

    [2010-11-05 18:18 UTC] rinseout at gmail dot com Similar problem on Vista home premium, PHP 5.2.5:

    <?php $numbers = array(0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009); foreach ($numbers as $number) print $number."->".number_format($number, 2, '.', ',')."
    "; ?>

    0.001->0.00 0.002->0.00 0.003->0.00 0.004->0.00 0.005->0.01 0.006->0.01 0.007->0.01 0.008->0.01 0.009->0.01

    as expected... however...

    <?php $numbers = array(78.221,78.222,78.223,78.224,78.225,78.226,78.227,78.228,78.229); foreach ($numbers as $number) print $number."->".number_format($number, 2, '.', ',')."
    ";

    ?>

    78.221->78.22 78.222->78.22 78.223->78.22 78.224->78.22 78.225->78.22 78.226->78.23 78.227->78.23 78.228->78.23 78.229->78.23

    ? 78.225->78.22 ?

    no fiddling with the precision parameter enabled me to fix this.

    [2010-11-05 18:37 UTC] [email protected] PHP 5.2.5? Upgrade!

  • (disco) in reply to kupfernigk

    Nice answer :heart:, but this was in the days before 3Dp, Stackoverflow, single currency, and legion other sources of "help".

    kupfernigk:
    There was a lot of argument at the time about whether, when buying n items at price x, the VAT should be calculated as (VAT on x)*n, or VAT on (nx).

    Please, I have only just gotten out of therapy over this sort of thing. :)

  • (disco) in reply to loose
    loose:
    But for some numbers it would unexpectedly round in the OTHER direction.

    no, looking at that linked (and C&Pd ) chain of emails the behavior is CORRECT

    what's "unexpected*" is that the multiplication there is performed with floating point math which is inaccurate ad so had a "rounding error" when converted back to base10.

    this is why you need to use decimal types for money.

    *to some

  • (disco) in reply to PJH
    PJH:

    A compiler warning perhaps? The comment comes across as ESL.

    Though the warnings are normally when possible truncation happens going from double to (single) float (though I did find this printf() error on some obscure platform.)

    Oh, ok. That scenario is remotely plausible. The alternate scenario would be a badly mangled submission, and we all know that doesn't happen.

    I'm just confused because in order for a flag to avoid this warning, wouldn't it have to be a run-time warning? I'd expect static analysis to warn about the possibility of the conversion even if that flag could be determined to be set always. I couldn't imagine a language to have a run-time warning of this. And I can't imagine a language where having the alternate path would void the warning. Both would be positively insane. Even having the warning in the first place is dubious.

    Maybe this function is the result of rote behaviour trained by warnings of double to float conversion? So because in my experience I had to work around warnings of double-to-float, I'm now guarding against warnings of float-to-double? Mistakenly applied tradition is a major source of WTF.

  • (disco) in reply to accalia
    accalia:
    .... right, because Java isn't a big enough on its own....

    yes, if there is no native time third party alternatives are acceptable.

    BigDecimal isn't third party1. It's shipped as part of Java and has been for decades. I linked to the Java 8 documentation for it.

    1Although there was a rumor that IBM actually wrote the code for BigDecimal and BigInteger and not Sun.

  • (disco) in reply to powerlord

    and yet my comment is no less valid. ;-)

    besides IIRC it was third party until.... java 1.3?

  • (disco) in reply to accalia
    accalia:
    Repeat after me:

    #The only correct type for currency is decimal. Any other type will cause trouble in the future.

    and that included integer types, because you will eventually have to change your precision and you can't do that sanely with integer stored decimals.

    While I agree with your assertion, I also note that the article never mentioned anything to do with currency. Floats and doubles work well (and fast) for quite a lot of different usage scenarios and sometimes converting from one to the other is a perfectly valid operation.

  • (disco) in reply to ashkante
    ashkante:
    While I agree with your assertion, I also note that the article never mentioned anything to do with currency.Floats and doubles work well (and fast) for quite a lot of different usage scenarios and sometimes converting from one to the other is a perfectly valid operation.

    They are all having a go at me, 'cos I happened to mention a currency example when explaining why you may need to roll your own :WTF: to resolve an issue. And in time honoured fashion resulting from generations of thinking like a shark (i.e. literally linear) that results in everybody fighting over scraps........

  • (disco) in reply to ashkante
    ashkante:
    While I agree with your assertion, I also note that the article never mentioned anything to do with currency.

    the article might not have, but @loose did.

    i would have left well enough alone if he hadn't mentioned currency conversion.

  • (disco) in reply to accalia
    accalia:

    the article might not have, but @loose did.

    i would have left well enough alone if he hadn't mentioned currency conversion.

    Ah, so it was my reading comprehension that threw a cog. Well, doesn't change that I agree with you re. floats and currency :)

  • (disco) in reply to accalia
    if ((what.thedailywtf.com/t/we-all-float-down-here/49773/10?u=loose.content().contains("currency conversion") || (what.thedailywtf.com/t/we-all-float-down-here/49773/4?u=loose.content().contains("currency conversion")) { @accalia = @accalia + 0.0000001 Internets;} else { @loose = @loose + 0.0000001 internets;}
    

    I was going to mention string conversion (in this reply), but my code threw an INT_OVERFLOW when it tried to count them.

    :p :trolleybus: :barrier: :plus: :any: :other: :number: :of: :similar: :themed: :emojis:

  • (disco) in reply to loose
    loose:
    My point wasn't about using floats or not. It was about rounding. Most system either round up or round down when confronted with the dreaded 0.5 of a penny, or 0.005 of a £. What happened here *and I must **stress** these are **pure** examples*, was certain numbers like 12.375 would round down to 12.37 rather than the expected round up to 12.38

    And, you realize, that some rounding methods, this is intentional? There are reasons to change the default of ".5 rounds up" to remove the fact that 10% of fractions would round up into someone else' favor?

    "This method treats positive and negative values symmetrically, and is therefore free of sign bias." https://en.wikipedia.org/wiki/Rounding#Round_half_to_even

    Using this knowledge, you can "Superman 3" your company a fraction of a penny per transaction and eventually take over the world - choosing the method that will best pad your bank account for each transaction.

    https://www.mathsisfun.com/numbers/rounding-methods.html

  • (disco)

    Look what you made me do with all this talk about currency:

    if (!isset($current_password)) {
    	$currentPassword = '';
    }
    else {
    	$currencyPassword = $currency_password;
    }
    

    Note: this is "quick hack" code and any attempts to discuss it's WTFy will be studiously ignored.

  • (disco) in reply to WernerCD

    I like this, especially when it comes to something like the Lottery. However, in very simplistic terms I would expect round([float]) to be very deterministic.

    For some languages rounding up or down is a compile feature, for others it is an optional parameter, or runtime configuration. Some have both. Either way you know what the result is going to be for whatever you put in.

    sheeeeesh.....

  • (disco) in reply to loose

    It is very deterministic... Round up? Round down? Round even/odd? Round towards zero? Away from zero? Figure out that which benefits The Company and it's Overlords. Simple really.

  • (disco) in reply to accalia
    accalia:
    and yet my comment is no less valid.

    Buttuming I'm parsing what you said correctly (hint: use commas) it looks like you've claimed it's not in native time despite not actually testing it.

    Then again, it is a bignumber format, so it probably is slower than one that isn't multi-precision.

    accalia:
    besides IIRC it was third party until.... java 1.3?

    There's no @since in the class documentation, which implies its been in core since Java 1.0.

  • (disco) in reply to powerlord
    powerlord:
    Buttuming I'm parsing what you said correctly (hint: use commasproof reading)

    ah... i see where the confusion happened

    accalia:
    yes, if there is no native timetype third party alternatives are acceptable.
    powerlord:
    Then again, it is a bignumber format, so it probably is slower than one that isn't multi-precision.
    almost guaranteed. ;-)
    powerlord:
    There's no @since in the class documentation, which implies its been in core since Java 1.0.
    well that wouldn't be the first time my memory was faulty.
  • (disco) in reply to accalia
    accalia:
    The only correct type for currency is decimal. Any other type will cause trouble in the future.

    Untrue generalization!

    You may use a float where the value it represents is an estimate, or represents a continuous variable that is denominated in currency.

    A perfect example is suggested by this wtf. You make a model to predict stock prices:

    1. The model uses derived quantities such as the time derivative of price. This value can have huge dynamic range, so a float is called for. Another example is the model uses a discrete-time filter. The units are in currency but, again, there may be large dynamic range.
    2. The model needs to feedback upon itself. Here, to prevent quantization error each step, you need to save the output, which is currency, as a quasi-continuous value.
    3. The output of the model will be a float, in which case you need to cast that back into a decimal or whatever.

    Another example is you're calculating the average selling price of a product over a large number of transactions. Again, it's an estimate, so non-exact data types are acceptable.

  • (disco) in reply to accalia

    Java only has 7 native types and hasn't added any in 20 years.

    I'll also take a moment to point out that .NET doesn't have native types in user code... they're all structs that box the native types.

  • (disco) in reply to dkf

    ... but the dev ought to also get a slap upside the head for the quantity of magical thinking involved in that code.

    I'd need to see more context. From the comments, it almost comes off as sarcastic, passive-aggressive parroting. My "Spidey Sense" is telling me that the dev was forced to do this, and isn't happy about it.

    Again, would need to see more from this dev to get a good read on it.

  • (disco) in reply to safarty
    safarty:
    You may use a float where the value it represents is an estimate, or represents a continuous variable that is denominated in currency.

    I still assert that it is better to use a decimal type there. because even if estimate at least then you don't get Base2/Base10 conversion errors.

    powerlord:
    Java only has 7 native types and hasn't added any in 20 years.
    wait, now you are asserting that BigDecimal isn't a native/firstparty type?
  • (disco) in reply to accalia
    accalia:
    wait, now you are asserting that BigDecimal isn't a native/firstparty type?

    He misspelled primitive, I think.

  • (disco) in reply to boomzilla
    boomzilla:
    He misspelled primitive, I think.

    ah. yes. if that's primitive types then yes. but i said native not primitive.

    of course if you can primitive is perferable to non-primitive types

  • (disco) in reply to boomzilla

    Yeah, whoops.

    I'm behind on my caffeine intake this morning.

  • (disco) in reply to accalia
    accalia:
    I still assert that it is better to use a decimal type there. because even if estimate at least then you don't get Base2/Base10 conversion errors.

    I agree that you minimize conversion errors, but the other factor is that non-binary data types, on anything that's not IBM Big Iron, is going to be painfully slow versus binary floating point.

  • (disco) in reply to safarty
    safarty:
    I agree that you minimize conversion errors, but the other factor is that non-binary data types, on anything that's not IBM Big Iron, is going to be painfully slow versus binary floating point.

    Given recent improvements in processor speed i categorize that argument as Premature OptimizationTM

    Code correctly first, then measure performance. Only apply optimizations once you've measured performance. then measure performance again after optimizing. if there's no significant improvement rollback the optimizations and try a different tack.

  • (disco) in reply to loose

    In Java, rounding is completely deterministic: it follows the IEEE 754 exactly. What you fail to take into account is that merely converting a string written in decimal to a binary floating-point number causes rounding in the general case. That conversion is also deterministic, by the way.

    According to the IEEE754 specification, 1.15 converts to about 1.149999976 as a float (expect more 9's with a double). If you multiply 12.5 by 1.149999976, you don't get 14.375, but 14.3749997 (which rounds to 14.37 because it's closer than 14.38). Note that converting the VAT-exclusive price will also introduce error (unless you're lucky to have a price that is a fraction with a power of 2 as the denominator). That error might go the opposite way to the VAT-rate error (in which case you're lucky, since it will decrease the overall error and possibly give you the expected result) or the same way (in which case, you're unlucky and might get a result that is several pence off instead of just one).

    What you need to fix is not the rounding (which works exactly as specified), but the conversion, and you can do it only by using a decimal floating-point type instead of a binary one (getting rid of the conversion, in other words). Once you are operating on exact values, you can implement whatever rounding rules you need.

  • (disco)

    :facepalm:

Leave a comment on “We All Float Down Here…”

Log In or post as a guest

Replying to comment #:

« Return to Article