Jeff Atwood Answers and Square Roots



  • @Spanky587 said:

    What is the square root of 4? It is 2. It is EXACTLY 2. It is not 1.999999999999 or 2.000000000001. It is EXACTLY 2, or if you want to use a floating point number it is 2.0000000000000000000000 -> infinite number of zeros.

    Just because a floating point value displays as "2" does not mean that it is the exact bitwise value that you would get by casting "2" to a floating point number. It just means that it is closer to 2 than it is to either of the other two nearest values bordering 2 that can accurately be represented at that precision. Here, try this and see what prints:

    #include <stdio.h>
    
    int main() {
        const float two = 2.0;
        printf("2.0 = 0x%8x\n", *(int *) &two);         // hex representation of (float) 2.0, should be 0x40000000
        printf("%f\n", *(float *) "\xfb\xff\xff\x3f");  // representation of 0x3ffffffb as a float
        printf("%f\n", *(float *) "\xfc\xff\xff\x3f");  // representation of 0x3ffffffc as a float
        printf("%f\n", *(float *) "\xfd\xff\xff\x3f");  // representation of 0x3ffffffd as a float
        printf("%f\n", *(float *) "\xfe\xff\xff\x3f");  // representation of 0x3ffffffe as a float
        printf("%f\n", *(float *) "\xff\xff\xff\x3f");  // representation of 0x3fffffff as a float
        printf("%f\n", *(float *) "\0\0\0\x40");        // representation of 0x40000000 as a float
        printf("%f\n", *(float *) "\x01\0\0\x40");      // representation of 0x40000001 as a float
        printf("%f\n", *(float *) "\x02\0\0\x40");      // representation of 0x40000002 as a float
        printf("%f\n", *(float *) "\x03\0\0\x40");      // representation of 0x40000003 as a float
        return 0;
    }
    

    Go execute that on https://www.codechef.com/ide... all but the highest and lowest print out exactly 2.000000, even though most of them aren't exactly 2.

    @blakeyrat said:

    It knew enough to display the value as an int.

    Why didn't it know enough to process the next calculator operation with an int value?

    Because that would require doing float -> string -> analyze -> integer -> subtract. Or, trying to roll your own code to figure out the "correct" value of the float, which would be TR‌:wtf:.

    Either way, you'd butcher the IEEE float's design which is actually supposed to minimize the accumulated error across multiple operations.


  • Notification Spam Recipient

    @Spanky587 said:

    What is (square root of 4) - 2

    My Windows calculator says it is -1.068281969439142e-19

    No repro.

    :hanzo:'d by @Scarlet_Manuka, but this one shows proof!



  • Or you could just not write shit code.

    [code]#include <math.h>
    #include <stdio.h>

    int main (int argc, char ** argv) {
    float fx = 4.0;
    double dx = 4.0;
    fx = sqrtf(fx) - 2.0;
    dx = sqrt(dx) - 2.0;

    printf ("float %f double %lf\n", fx, dx);

    return 0;
    }[/code]

    $ clang foo.c
    $ a.out
    float 0.000000 double 0.000000
    


  • What about long double and __float128?



  • How precisely do you want to specify your maybe-zero?



  • Well, I'm pretty sure non-scientific mode uses a 64-bit mantissa, and long double has a 64-bit mantissa. And __float128 is the only float type I know of that is larger and also usable directly by the processor.



  • @anotherusername said:

    Because that would require doing float -> string -> analyze -> integer -> subtract.

    I don't think it's a WTF to do the second operation using the result of the first one as displayed on the screen. In fact, I think that's the normal and expected behavior.



  • You'd have your calculator round the binary value to its decimal representation after every calculation? Why?



  • I'm using Windows 7 64-bit and my windows calculator tells me that the (square root of 2) - 2 is 0.

    Technically, that's only half correct through as it assumes the square root is positive. The other answer is -4.

    Edit: Actually, I did them as separate operations (hitting = between operations). Apparently when you do them both before hitting equals, it does it wrong. No idea why that is.



  • So that if you do square root of 4, then subtract two, you get the correct answer.



  • At the expense of getting more other wrong answers that are less obvious.



  • If it's not worth showing those digits on the screen, it's not worth keeping them for the next step of the operation.



  • @powerlord said:

    I'm using Windows 7 64-bit and my windows calculator tells me that the (square root of 2) - 2 is 0.

    Windows 7 Enterprise SP1, 64-bit:

    (standard)

    (scientific)

    @blakeyrat said:

    If it's not worth showing those digits on the screen, it's not worth keeping them for the next step of the operation.

    You can't use the digits on the screen. You're not calculating in base 10, you're calculating in base-2. You have to use the closest base-2 float, which is quite likely to be more wrong than the base-2 float you had before you converted it to the decimal number you showed on the screen.



  • @anotherusername said:

    You can't use the digits on the screen.

    Yes you can.

    I didn't read the rest of what you typed because the first sentence was so ludicrously wrong.



  • Your computer uses base-10 for internal computation?



  • @anotherusername said:

    Your computer uses base-10 for internal computation?

    No it does not.



  • Then the most you can do would be to use an approximation of the digits on the screen.

    Which is what I said, if you would've read the rest of my post.



  • Guess you shouldn't have started it with a blatant lie then.



  • You said that you could use the digits on the screen, implying that you could use that exact number for your next calculation. I said no you can not, because you can't.

    To "use" them implies to calculate with them. If you meant the general "use" sense, then why not use the number on the screen to wipe your ass, and then calculate with 1 because it's easier.



  • @anotherusername said:

    Then the most you can do would be to use an approximation of the digits on the screen.

    For an application like calculator, where performance is not an issue, you could perform base 10 computations just fine. You've never written an arbitrary precision class using binary coded decimals or the like for a class project? (BCD makes printing the numbers back out easy).



  • Recreating all the basic and scientific math functions just so you could do base-10 calculations would be TR⁠:wtf:.



  • Considering they broke the square root, I don't think giving the users the expected behavior is that wrong.

    Also, you just need a function to convert from BCD to binary and back. Many binary numbers will map to a single BCD number, but any one BCD number maps back to only one binary number. So there you have the normalization function you need to provide reliable results. So 2.000000000000000000001 will be shown to the user as 2, and then when used again it will just be 2, not 2.000000000000000000001. No need to recreate every function.



  • @Kian said:

    you just need a function to convert from BCD to binary and back. Many binary numbers will map to a single BCD number, but any one BCD number maps back to only one binary number. So there you have the normalization function you need to provide reliable results

    You already have that, except instead of BCD it uses ASCII. It's called "converting the number to a string", and I've already described why the base-2 -> base-10 -> base-2 process at each calculation step is not a good idea.

    There's really no way around it. Converting base-10 numbers to base-2 and then subtracting them is just fraught with peril. You'll always run into certain edge cases that are glaringly, obviously wrong. E.g., even though Javascript happens to get Math.sqrt(4) - 2 right, simple subtraction still doesn't work:

    (Windows calculator gets 0.3 - 0.2 - 0.1 right.)



  • @Spanky587 said:

    If you had a magic wand to make one change in technology right now, what would it be?

    I'd make it all work. And since it's a magic wand, I don't have to make it make sense, it's literally magic now. Because now all the work's done, and we aren't needed anymore, and can do something where there's less bullshit.

    Passwords are the enemy

    And that's why most of my services have SSO, based on my computer being the device, not the smartphone, because it just works, and I haven't been hacked yet.

    Prominent people, and accounts that have value (like bank account) can use tokens to enhance their security.

    Comon my bank.... get on board.... even WoW has better security.

    Look, I solved it.... without passwords.... and without a wand.

    Because it's a solved problem.

    Fucking hell...

    It never really made sense to open source Stack Overflow -- ask yourself, how many Stack Overflow clones have flourished?

    I've wanted a SO like for businesses for a long time.

    Wiki's are great, but they aren't direct.

    And sure, just go search the wiki is an easy out for not having an open platform to share information.

    There's naturally tons of downtime in the business world. I don't care how much people are pretending to be busy while sitting on the shitter for hours playing with their smartphone. We have the downtime to address questions.

    And for some reason, Q&A is tons easier to search than wiki or a forum.

    Why hasn't there been any open source copies?

    Because it's a large technological hurdle that is semi-solved by forums and wiki. There's too much effort for too little gain, in the eyes of business management.

    Maybe I'll write a closed-end product to sell to companies. Lord knows company communal software is so stale that information goes there to die.

    Do you remember a site called Experts-Exchange? No? That means we succeeded at our original goal.

    You succeeded at being better than a pile of shit.

    Good job...

    but when you start getting dozens or hundreds of "answers" you don't have Q&A, you have a discussion with no clear answers, just opinions.

    And you just described the science research field.

    Dozens of pointless research soaking up tons of research grants.

    Let's let popular opinion upvote them.

    I wonder how many votes the "Does big boobs make you a target on beaches" campaign will get.

    Discourse, on the other hand, is explicitly a system of discussion and opinion. There is no right and wrong.

    :spittake:

    But there's TOXICTM

    Fucking hell, the arrogance....

    It works at three levels

    Funny you didn't include the 0th level.

    You know, the level where people game the system to get quick votes by posting a half answer before someone else can post a good answer.

    It can be rude, offensive, misinformed, misguided, or just plumb crazy -- but it can't be objectively wrong.

    Or TOXIC, which makes you wrong.... and banned.


  • Discourse touched me in a no-no place

    @anotherusername said:

    You're not calculating in base 10, you're calculating in base-2.

    Smart people use a decimal data type instead of a floating-point one for such calculations and never worry about this nonsense.


  • ♿ (Parody)

    @FrostCat said:

    Smart people use a decimal data type instead of a floating-point one for such calculations and never worry about this nonsense.

    Meh...you still end up with tiny approximations due to representation of real numbers. It probably makes sense to truncate fractions in operations that are sooooooo close to integers. I don't know what epsilon I'd use, but it would likely be based on the errors you get from common things like square roots or trig functions.



  • Regardless of whether a sensible programmer would use a proper numerics library, in this case, it makes no sense to witter on about float vs int. Why?

    Because 4 is a power of 2. As such, it has an exact representation in floating point. Its square root is also a power of 2. It also has an exact representation in floating point. 2 is a power of 2. it has an exact representation in floating point. Zero has an exact representation in floating point. -4 has an exact representation in floating point. In short, every element in this calculation, including the answers, has an exact representation in base-2 floating point. There's no rounding from decimal to binary representation needed, because they are all exact in base-10 as well. That's why the trivial C code I pasted earlier works.

    Floating point is a shit idea if you're writing a calculator and care about accuracy, but it's not the problem here.


  • Trolleybus Mechanic

    I'm sure if we just programmed the calculator in Discourse, that would solve it.

    First, generate an object for every number that can exist. (Per user, because numbers are unique!)

    Then let the user enter a calculation.

    Then do an Ajax call to get all the numbers, because you never know which ones will actually be needed.

    Do the calculation client-side, because the server is way too busy failing it's Apdex scores to add 1+1.

    Finally, show the answer in a toaster with a message criticizing the user for doing math rather than being social. Unless the calculation fails, in which case show "1+1 = 502 OK"



  • You forgot to never delete any previous calculation and allow infiniscrolling of the entire history. Instead of repeating a calculation, the user can just search for the answer. Easy!



  • I think you missed the opportunity of setting up a separate number server, in case someone else needs numbers as well. It should calculate the numbers on the fly.


  • Trolleybus Mechanic

    @NedFodder said:

    You forgot to never delete any previous calculation and allow infiniscrolling of the entire history. Instead of repeating a calculation, the user can just search for the answer. Easy!

    People only use the first 10% and last 10% of any calculation anyways. The rest of the history is just noise that only mathematicians care about.



  • But what if the history gets too large? You need a "Summarize this History" button to turn the entirely too long

    2+2
    4
    4+4
    8
    8+7
    15
    

    into much more manageable:

    2+2
    15
    

    Filed under: inb4 long calculations are :doing_it_wrong:


  • Trolleybus Mechanic

    You can crowdsource answers from StackCalculator

    👦 What's the square root of 4?

    Accepted Answer
    987 points
    👻 Import jQuery and you can use $.Math.

    ❌ Answer provided after calculation was closed. Marked as invalid. :doing_it_wrong:
    18 points
    👴 The answer is "2". 2 * 2 = 4.



  • @loopback0 said:

    >So-called "civilized discourse" is some of the blandest, boring, mind-numbing conversation there is. It's completely devoid of original thought. This is because original thought might just hurt somebody's feelings, which is considered totally unacceptable for some reason. Negativity, especially negativity that's the most legitimate and correct, is also not tolerated, again because somebody's feelings might get hurt. Discussion forums where that's the policy quickly become politically correct mutual masturbation sessions, where the mindlessness is repeated again and again. It's funny, though, that the moderators at such communities are often the biggest tyrants around. The louder they scream about how critical it is to be tolerant of others, the faster and harder they'll crack down on anyone who dares to show any sort of originality!

    Kind of like censoring dissenting offensive opinions in order to promote "diversity" in discussion.



  • @powerlord said:

    I'm using Windows 7 64-bit and my windows calculator tells me that the (square root of 24) - 2 is 0.

    FTFY

    @powerlord said:

    Technically, that's only half correct through as it assumes the square root is positive. The other answer is -4.

    No. The square root is positive, by definition. If you want to get −2 as the result of the square root operation, you have to take the negative square root, which is explicitly prefixed with a − if you write it in mathematical notation.

    @powerlord said:

    Edit: Actually, I did them as separate operations (hitting = between operations). Apparently when you do them both before hitting equals, it does it wrong. No idea why that is.

    [wild ass guess] When you hit = and perform an operation on the result, the displayed value is used as input for the new operation, even if it is rounded from the higher-precision internal value.
    When you don't hit =, the internal value (with higher precision than what's displayed) is used instead.



  • @Lorne_Kates said:

    First, generate an object for every number that can exist. (Per user, because numbers are unique!)

    These are served from a CDN of course.



  • @OffByOne said:

    No. The square root is positive, by definition
    Obpendantry: Incorrect - the square root of 4 is ±2. The principal square root of 4 is 2; that is positive, by definition.
    @OffByOne said:
    [wild ass guess]

    Is wrong. At no point doesshould the calculation involve any inaccuracy. It should not matter if the value is rounded at any point in the calculation, because the entire calculation is a simple case of manipulation of the exponent (the mantissa remaining zero for all values). Something is bugged, but it's not the use of floating point per se.

    It also breaks for sqrt (9) - 3, though.



  • @tufty said:

    @OffByOne said:
    No. The square root is positive, by definition
    Obpendantry: Incorrect - the square root of 4 is ±2. The principal square root of 4 is 2; that is positive, by definition.

    Obpendantryception: the square root must be unique (otherwise it would be a square root), so it only makes sense to say "the square root of 0".

    The principal square root of a number x is unique, so that makes sense. Thanks for telling me about the phrase "principal square root" btw.

    ESL joker card: in my native language, "the square root of x" is, for disambiguation purposes, defined to be the number a that satisfies a2 = x and a must be non-negative.
    −a is called "the negative square root".
    My assumption that the same terminology carried over to English was wrong.

    @tufty said:

    @OffByOne said:
    [wild ass guess]

    Is wrong. At no point doesshould the calculation involve any inaccuracy. It should not matter if the value is rounded at any point in the calculation, because the entire calculation is a simple case of manipulation of the exponent (the mantissa remaining zero for all values).

    My guess about what's going on internally is only wrong if the algorithm used for calculating the square root does exponent manipulation for powers of two and uses some other (approximate) technique for non-powers of two.
    The evidence provided supports my assumption that powers of two are not considered a special case in the algorithm used.
    I stand by my WAG.

    Mind you, I completely agree with you that there shouldn't be any inaccuracy (for radicands that are powers of two).

    @tufty said:

    Something is bugged, but it's not the use of floating point per se.

    No. It's the algorithm used to calculate the square root.


  • ♿ (Parody)

    @OffByOne said:

    Obpendantryception: the square root must be unique (otherwise it would be a square root), so it only makes sense to say "the square root of 0".

    We need to go deeper (:giggity:)! Depends on what sort of numbers you're talking about.


  • BINNED

    @tufty said:

    At no point doesshould the calculation involve any inaccuracy.

    You are outputting results to the user. The '=' means that the calculation is final. When starting a new calculation based on the previous result the calculator should handle the result as if the calculator was cleared and the starting number was entered by the user. Especially if there since there generally is no indication to the user that more details are carried over. Otherwise the user has no chance of recalculating and getting the same results as the calculator.



  • @tufty said:

    the entire [sqrt] calculation is a simple case of manipulation of the exponent

    I beg your pardon?

    The significands are different.

    (take those hex values, reverse the endianness, and escape:)



  • Irrelevant.

    The representation of 2 in floating point is exact. The representation of 4 in floating point is, again, exact. The result of fsqrt, the intel floating point square root opcode, which has existed since the 8087 coprocessor, when used on the floating point representation of 4 (which is exact) is the floating point representation of 2 (which is also exact). Likewise for sqrtss and sqrtsd.

    At no point is the result inexact.

    4 => exact.
    sqrt(4) => exact
    2 => exact
    2 - 2 => exact
    sqrt(4) - 2 => exact



  • OK, points for pendantry. Square root of 4 is a simple manipulation of the exponent.



  • If the number is perfectly exact, yeah. It wouldn't make a whole lot of sense to write an extra edge case for that; you're dealing with floating points and most numbers aren't perfectly exact. It'll still probably fail to correctly handle something like sqrt(4.1 - 0.1).



  • @boomzilla said:

    @OffByOne said:
    Obpendantryception: the square root must be unique (otherwise it would be a square root), so it only makes sense to say "the square root of 0".

    We need to go deeper (:giggity:)! Depends on what sort of numbers you're talking about.

    Re-emboldened for clarity.

    My point is that you should only call something "the …" if it's unique. If it's not guaranteed to be unique, you'd better call it "a …".
    In mathematics that's a well-understood rule, at least in my native language. English might differ, I have NFC.

    Using different sorts of numbers makes the number of square roots increase (assuming you're talking about the square roots of complex numbers, for example).



  • It's generally understood that when you're talking about "the square root" you're referring to the principal square root, and it is unique. Otherwise you say "a square root" or plural, "square roots".



  • @anotherusername said:

    It'll still probably fail to correctly handle something like sqrt(4.1 - 0.1).

    I don't think it does. It fails for any number you can exactly enter both x and sqrt x at the calculator interface.

    Exact keypresses :

    4 √ - 2 = : -8.1648465955514287168521180122928e-39
    4 √ - 1 = : 1
    9 √ - 3 = : 1.1546388020691628168216106791278e-37
    9 √ - 1 = : 2
    9.0601 √ - 3.01 = : 7.8835139928266946663002596427648e-38
    9.0601 √ - 0.01 = : 3

    See what you did there? You made me fire up a VM running Win7 to check this. Because although there's a lot of people blathering on about "floating point blah blah blah", there seem to be very few people actually checking what they are saying. Despite it being trivially easy to do.



  • Now try ( 4.1 - 0.1 ) √ - 2... you'll get a different wrong result than you got for 4 √ - 2.

    Point being, even if you get your sqrt function to return exactly 2.0 when you pass in exactly 4.0, it's still going to break when you pass in not-exactly, but should be exactly 4.0. And there are a lot of floating-point operations that should result in exactly 4.0, but won't quite exactly.


  • ♿ (Parody)

    @OffByOne said:

    Re-emboldened for clarity.

    But you went on to mention "the square root of 0" without specifying what numbers you were using!



  • So what? It's still wrong, and it's still a bug in widnose crapulator, not a fundamental issue with floating point calculations.

    [code]
    #include <math.h>
    #include <stdio.h>

    int main (int argc, char ** argv) {
    float fx = 4.0;
    printf ("float %f %08x\n", fx, ((unsigned int)&fx));
    fx += 0.1;
    printf ("float %f %08x\n", fx, ((unsigned int)&fx));
    fx -= 0.1;
    printf ("float %f %08x\n", fx, ((unsigned int)&fx));
    fx = sqrtf(fx) - 2.0;

    printf ("float %f %08x\n", fx, ((unsigned int)&fx));
    return 0;
    }
    [/code]
    copy. paste. compile. run.


Log in to reply