110

I need to get the left hand side integer value from a decimal or double. For Ex: I need to get the value 4 from 4.6. I tried using Math.Floor function but it's returning a double value, for ex: It's returning 4.0 from 4.6. The MSDN documentation says that it returns an integer value. Am I missing something here? Or is there a different way to achieve what I'm looking for?

radbyx
  • 8,605
  • 18
  • 75
  • 119
  • 3
    _The MSDN documentation says that it returns an integer value_. [MSDN documentation](http://msdn.microsoft.com/en-us/library/e0b5f0xb(v=vs.110).aspx) states that Math.Floor returns System.Double, not integer. – broadband Jun 11 '14 at 11:50
  • An integer ***value*** is effectively needed, but it does not mean that it can be stored in an "int" or "long". A "double" successfully stores all integer values in a much wider range than just "int" Note that some integer values may be rounded when the mantissa part has not enough bits to store all digits of the integer value, when its base-2 exponent goes above 52: this rounding of integer values in "double" may occur for integers above 2^52 or below -2^52 but the result will still be the nearest integer representable; if you use "(long)Floor(x)", the conversion could be largely wrong. – verdy_p Dec 15 '15 at 21:07
  • Note however that the valid range of integer vallues that may be represented in a "double" is extremely large, with absolute values up to: (1 + (1 − 2^−52)) × 2^1023 ≈ 1.7976931348623157E308; it is much more than 2^63-1 with "long". However the range of integers that can all be stored distinctly is more restricted, because a "double" only has 52 bits for the mantissa (plus 1 bit implied for the most significant bit, not stored), meaning that "double" can store only integers exactly oonly when their absolute value is below 2^53. – verdy_p Dec 15 '15 at 21:17
  • Unfortunately,Math.Floor() does not return a variable "Number" type internally using "Long" if possible, or "Double" otherwise only for large rounded integers. And the standard Math library does not handle such unified variable number type. There exists other math libraries implementing an unified number type, including Long, Double, or large integers encoded in packed decimal or binary without loss of supported range or precision. – verdy_p Dec 15 '15 at 21:17

6 Answers6

154

The range of double is much wider than the range of int or long. Consider this code:

double d = 100000000000000000000d;
long x = Math.Floor(d); // Invalid in reality

The integer is outside the range of long - so what would you expect to happen?

Typically you know that the value will actually be within the range of int or long, so you cast it:

double d = 1000.1234d;
int x = (int) Math.Floor(d);

but the onus for that cast is on the developer, not on Math.Floor itself. It would have been unnecessarily restrictive to make it just fail with an exception for all values outside the range of long.

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • double is wider than the range of double? Think you meant long. :) – Andrew Coleson Aug 28 '09 at 19:58
  • 2
    Floor returns integer representation of double, and it returns double for scientific calculations, this answer is not correct because double has 64 bits and long also has 64 bits, but double can not store exact digits of lower significant bits even if it can be stored correctly in long. – Akash Kava Aug 28 '09 at 20:18
  • 1
    @Jon: how come you haven't weighed in on the debate raging over how to make a positive number negative in C#?: http://stackoverflow.com/questions/1348080/convert-a-positive-number-to-negative-in-c – MusiGenesis Aug 28 '09 at 20:23
  • @Andrew: Fixed, thanks. @MusiGenesis: I'm browsing over flaky GPRS; it's painful as hell. This will be my only answer today. @Akash: Which bit of my answer do you consider incorrect? Just because both `long` and `double` use the same number of bits doesn't mean they have the same range. Look at `double.MaxValue-double.MinValue` and `long.MaxValue-long.MinValue`... There are integers which are in the range of `double` (even if they aren't all exactly representable) but outside the range of `long`. My example shows such an integer. – Jon Skeet Aug 28 '09 at 20:45
  • 3
    @Jon: take your time. It turns out the community discovered that multiplying a positive number by -1 will make it negative. All is well on StackOverflow. – MusiGenesis Aug 28 '09 at 21:12
  • who guarantee that `(int) Math.Floor(d);` cast will always work? In my code I've used `(int) IGNORE_RATIO*Volume;` where `double IGNORE_RATIO = 0.15` and `int Volume = 100`. Result of such operation was not `15` as I was thinking, but `0` instead. That's because `(int) 15.0 = 0` (i don't know why) – Oleg Vazhnev Jun 26 '12 at 17:54
  • 1
    @javapowered: No, (int) 15.0 is *not* 0. Something else has gone wrong, but we can't tell what from just that. Please create a short but complete program demonstrating this, and then ask a question. I suspect you'll find it hard to reproduce... – Jon Skeet Jun 26 '12 at 17:56
  • 1
    @MusiGenesis: (int) IGNORE_RATIO * Volume is computed as (int) 0.15 * Volume, but the typecast applies only to the ratio, not the result of the product, and you get 0 * Volume i.e. zero ! Use (int)(IGNORE_RATIO * Volume) instead to solve YOUR bug. – verdy_p Dec 15 '15 at 21:23
  • The answer is not incorrect. Note however that if that magnitude of the `double` brings it outside the range of a `long`, i.e. if the absolute value exceeds `9.2233720368547758e18`, then the limited precision of `double` already makes the `Floor` function completely meaningless. Any `double` so huge will be formally an integer (in fact an integer which is "very even", i.e. whose integer factorization contains 2 to a high power). Example: `1e20 / 3.0` should ideally non-integral, but it is in reality a `double` which is represented as an integer divisible by `4096` or `2**12`. – Jeppe Stig Nielsen Dec 15 '15 at 23:39
  • @verdy_p: huh? I think you meant to reply to `javapowered`. – MusiGenesis Dec 16 '15 at 14:56
11

According to MSDN, Math.Floor(double) returns a double: http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx

If you want it as an int:

int result = (int)Math.Floor(yourVariable);

I can see how the MSDN article can be misleading, they should have specified that while the result is an "integer" (in this case meaning whole number) it is still of TYPE Double

Neil N
  • 23,912
  • 15
  • 82
  • 141
  • Thank you for your reply. Actually I was looking at this article: http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx But anyways, I will try your suggestion. Thank you. –  Aug 28 '09 at 19:33
  • Well true, it does say at the top "returns an integer" but the type is specified below it: public static double Floor(double d) – Neil N Aug 28 '09 at 19:35
  • 3
    integer != `int` (http://www.answers.com/integer) - integers *can* be stored in `Double` (see Jon's answer), and there are an infinite number of integers that cannot be stored in an `int`. – Shog9 Aug 28 '09 at 19:45
  • Shog, I didnt say they couldn't. What I said was "it is still of TYPE Double" – Neil N Aug 28 '09 at 20:21
  • 1
    @Neil: right - just wanted to stress the difference between "integer" (name of a set) and `int` (name of a type). – Shog9 Aug 28 '09 at 20:34
4

If you just need the integer portion of a number, cast the number to an int. This will truncate the number at the decimal point.

double myDouble = 4.6;
int myInteger = (int)myDouble;
Jon Seigel
  • 11,819
  • 8
  • 53
  • 90
  • 2
    Important to note that casting to `int` behaves differently to `Floor`, for negative numbers. `Floor` will always truncate to the most negative number, whereas casting to `int` will truncate towards 0. – Magnus Dec 08 '16 at 21:12
0

That is correct. Looking at the declaration, Math.Floor(double) yields a double (see http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx). I assume that by "integer" they mean "whole number".

Jon Onstott
  • 12,491
  • 15
  • 77
  • 128
0

Floor leaves it as a double so you can do more double calculations with it. If you want it as an int, cast the result of floor as an int. Don't cast the original double as an int because the rules for floor are different (IIRC) for negative numbers.

plinth
  • 45,549
  • 9
  • 75
  • 118
0
Convert.ToInt32(Math.Floor(Convert.ToDouble(value)))

This will give you the exact value what you want like if you take 4.6 it returns 4 as output.

ivaigult
  • 4,619
  • 5
  • 27
  • 48