0

I wanted to know if the result of std::sqrtf is exact if the value is actually squared.

int value = ...;
int root = (int)sqrtf((float)value); // is this safe?

Note that value is integer and not always squared. in that case I want to truncate the result.

M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
  • 3
    Note that `root * root` might not be exactly representable as a `float`. – Bob__ Mar 12 '23 at 19:46
  • 1
    I just updated my question, sorry, I think it's important that value is int casted to float – M.kazem Akhgary Mar 12 '23 at 19:49
  • With your updated question, the answer depends on the target architecture's implementation of `float`. You might be asking about the behavior of [IEEE 754 floats](https://stackoverflow.com/questions/5777484/how-to-check-if-c-compiler-uses-ieee-754-floating-point-standard). – Drew Dormann Mar 12 '23 at 19:53
  • 1
    It's not guaranteed. An integer could have a square root whose exact value is just fractionally less than an integer (and not representable as a float). The sqrt routine could then correctly round that value up to that integer, thus defeating your requirement to truncate. Whether such a thing happens in practise I don't know. – john Mar 12 '23 at 19:55
  • `(int) sqrtf((float) 2147395599)` gives the wrong answer because `2147395599` rounds to the wrong float – Artyer Mar 12 '23 at 20:28
  • Re: `// is this safe?` -- define "safe". – Pete Becker Mar 12 '23 at 22:02
  • 1
    Short answer: no. The only way for the result to be exact is if a `float` can represent all possible values of `root*root`. A `float` is typically a 32-bit representation, and `int` is *often* a 32-bit representation. Which (in that case) means an `int` can represent values that a `float` cannnot (and vice versa). If you want to compute the "integer square root" exactly (in the sense of "value of `root` such that `root*root <= value`) don't use floating point at all - there are (relatively simple) algorithms available if you search for that term. – Peter Mar 13 '23 at 00:26
  • @M.kazem Akhgary, `long root = lround(sqrt((double)value));` will get you closer - albeit not a _truncate_. Have you considered `(int)sqrt((double)value);`? (that will _usually_ work.) What is your higher level goal? – chux - Reinstate Monica Mar 13 '23 at 08:23

0 Answers0