Length of the integer part of a double in C without math.h
You say it "works fine" in all your tests, but you didn't show us the tests.

Unfortunately, it failed the very first test I wrote:

#include &lt;gtest/gtest.h&gt;

TEST(length, zero)
{
    EXPECT_EQ(1, length(0));
}


Of the next batch, one_minus fails for the same reason:

TEST(length, one)
{
    EXPECT_EQ(1, length(1.0));
}

TEST(length, one_plus)
{
    EXPECT_EQ(1, length(1.0 + 1e-12));
}

TEST(length, one_minus)
{
    EXPECT_EQ(1, length(1.0 - 1e-12));
}


TEST(length, two)
{
    EXPECT_EQ(1, length(2.0));
}

TEST(length, two_plus)
{
    EXPECT_EQ(1, length(2.0 + 1e-12));
}

TEST(length, two_minus)
{
    EXPECT_EQ(1, length(2.0 - 1e-12));
}


TEST(length, ten)
{
    EXPECT_EQ(2, length(10.0));
}

TEST(length, ten_plus)
{
    EXPECT_EQ(2, length(10.0 + 1e-12));
}

TEST(length, ten_minus)
{
    EXPECT_EQ(1, length(10.0 - 1e-12));
}


We can fix this by adding a simple check before the first division:

if (number &lt; 0) number *= -1;
if (number &lt; 1) return 1;


Let's add some more tests:

TEST(length, zillions)
{
    EXPECT_EQ(36, length(1.0e35));
}

TEST(length, negative_zillions)
{
    EXPECT_EQ(36, length(-1.0e35));
}


Now we just need some tests for invalid inputs (infinities, NaNs, etc) and we're golden.



Let's look at the implementation now:

while (number &gt; 1) {
    result++;
    number /= 10;
}
return result + (number == 1);


We can avoid adding number == 1 if we include that case within the while loop:

while (number &gt;= 1) {
    result++;
    number /= 10;
}
return result;


And our tests prove we haven't broken it.

We might now want to improve speed for large numbers: consider our zillions test that loops 36 times.  We could shorten that, at a very small cost to lower numbers by first looping (say) 6 digits at a time:

int result = 0;
while (number &gt;= 1e6) {
    result += 6;
    number /= 1e6;
}
while (number &gt;= 1) {
    result++;
    number /= 10;
}
return result;


When I try this, it initially shows promise, but then fails the zillions tests with an off-by one error.  Is there a subtle difference in rounding between repeatedly dividing by ten and repeatedly dividing by a million when you're dealing with inexact numbers?  Actually, the problem is with our constant - 1.0e35 is most closely represented as 99999999999999999997871448567840768, so we suffered a rounding error in our test - it happened that sequential division by ten introduces a rounding error that compensates for this, and we wrongly pass!

Which brings me neatly to the alternative implementation.  The most convenient tool for measuring digits in the integer part isn't in &lt;math.h&gt; at all - it's in &lt;stdio.h&gt;!  We can ask printf to measure the length for us:

#include &lt;stdio.h&gt;

int length(double number)
{
    /* "unround" the number, as printf rounds to nearest */
    number += .5 - (number &gt; 0);
    /* format the sign, then subtract one, so we don't count
       minus as a digit */
    return snprintf(NULL, 0, "%+1.f", number) - 1;
}


Note that I've left the handling of NaNs and infinities in this version as an exercise...