0

Given const auto foo = 13.42 I would like to get the numbers fractional part, so .42

I'm leaning toward just using fmod like: fmod(foo, 1.0)

But I could also just do foo / static_cast<int>(foo) - 1.0 Or perhaps some other mystical method.

Would there be a motivation for me to not simply use fmod?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288

1 Answers1

6

Two ways I can think of, either a cast or rounding down with std::floor

int main()
{    
    const auto foo = 13.53;

    auto firstWay = foo - static_cast<long long>(foo);  // Truncating via cast and subtracting

    auto otherWay = foo - std::floor(foo); // Rounding down and subtracting

    return 0;
}

Quick Bench Result shows the fmod approach as the slowest option by far, and the cast as the fastest: QuickBench

Carl
  • 2,057
  • 1
  • 15
  • 20
  • 2
    I much prefer the second version. The first could blow up as a double can store a number larger than what can be held in an `int`. – NathanOliver Mar 19 '18 at 21:22
  • You should probably cast that to `long` instead of `int`. – Ron Mar 19 '18 at 21:23
  • @NathanOliver Would the `floor` method be preferable to `fmod` then? – Jonathan Mee Mar 19 '18 at 21:24
  • 1
    @Ron Even `long` isn't right as `sizeof(long)` can equal `sizeof(int)` – NathanOliver Mar 19 '18 at 21:24
  • 1
    `Long long` then – Carl Mar 19 '18 at 21:25
  • 1
    @JonathanMee I'm not sure. It can probably be implemented cheaper/faster than `fmod` but I'd benchmark to find out. – NathanOliver Mar 19 '18 at 21:25
  • @NathanOliver I believe `long long` should be sufficient as even a `long double` uses that in most implementations as it's mantissa. – Jonathan Mee Mar 19 '18 at 21:25
  • @JonathanMee if you're going to hard code a type then `long long` should be okay. I'm hesitant though as I'm pretty sure there is nothing stopping double from being larger than 64bits. – NathanOliver Mar 19 '18 at 21:28
  • @NathanOliver You mean nothing stopping a `long double` from having a larger mantissa than a `long long` right? I thought a `double` was always 64-bits? – Jonathan Mee Mar 19 '18 at 21:30
  • A type is never always a certain amount of bits. The only guarantee is that they are sized a certain way relative to the other types. See the standard for more details. – Mike Borkland Mar 19 '18 at 21:35
  • 2
    @JonathanMee The relavant standardies is *There are three floating-point types: float, double, and long double. The type double provides at least as much precision as float, and the type long double provides at least as much precision as double.* AFAIK there is no size requirement for `double` besides what I just quoted and it needs to be able to store the value `1e+37`. That means you can have a 128 bit double and be standard compliant. – NathanOliver Mar 19 '18 at 21:36
  • @MilesBudnek Good catch, that is more in line with what GCC yielded. I'll update with your link. – Carl Mar 19 '18 at 22:01
  • 1
    @NathanOliver: There are requirements on `double` beyond what you've quoted. For example, `double` has to provide at least 10 decimal digits of precision, where `float` only has to provide `6`. Most easily found in the C standard, section 5.2.4.2.2/11. – Jerry Coffin Mar 19 '18 at 22:06