Double -> Integer

  • Thread starter Thread starter Armin Zingler
  • Start date Start date
A

Armin Zingler

Hi,

is there a function in the Framework that cuts the places
after the decimal point of a Double and converts to an Integer
_without_ performing any rounding (as Convert.ToInt32 does)?
I mean, what the IL code "conv.i4" does? ATM I'm using a function
that exactly does what I need in a C++ helper library:

static int ToInt32(double value)
{
return int(value);
};

But I want to get rid of it because a whole library for this
function is oversized and because this simple function should be
in the Framework, shouldn't it?
 
Armin Zingler submitted this idea :
Hi,

is there a function in the Framework that cuts the places
after the decimal point of a Double and converts to an Integer
_without_ performing any rounding (as Convert.ToInt32 does)?
I mean, what the IL code "conv.i4" does? ATM I'm using a function
that exactly does what I need in a C++ helper library:

static int ToInt32(double value)
{
return int(value);
};

But I want to get rid of it because a whole library for this
function is oversized and because this simple function should be
in the Framework, shouldn't it?

Well... Math.Truncate? You would of course have to case the return to
an integer..
 
Am 10.01.2011 23:20, schrieb Tom Shelton:
Armin Zingler submitted this idea :

Well... Math.Truncate? You would of course have to case the return to
an integer..

Yes, but how to convert then?
 
After serious thinking Armin Zingler wrote :
Am 10.01.2011 23:20, schrieb Tom Shelton:

Yes, but how to convert then?

I don't understand?

Module Module1

Sub Main()
Dim d As Double = 7.9999999
Dim i As Integer = CInt(Math.Truncate(d))
Console.WriteLine(i)
End Sub

End Module

output = 7
 
Am 11.01.2011 01:36, schrieb Tom Shelton:
After serious thinking Armin Zingler wrote :

I don't understand?

Module Module1

Sub Main()
Dim d As Double = 7.9999999
Dim i As Integer = CInt(Math.Truncate(d))
Console.WriteLine(i)
End Sub

End Module

output = 7

CInt perform rounding. That's what I want to avoid because it's unnecessary
and costs time. It's unnecessary because Truncate has been called before.
 
Am 11.01.2011 01:36, schrieb Tom Shelton:
The code above emitts:

conv.i4

whereas CInt just calls Convert.ToInt32, and it's IL code is:

---------->

.locals init (int32 V_0,
float64 V_1,
int32 V_2,
float64 V_3)
IL_0000: ldarg.0
IL_0001: ldc.r8 0.0
IL_000a: blt.un.s IL_0043
IL_000c: ldarg.0
IL_000d: ldc.r8 2147483647.5
IL_0016: bge.un.s IL_007a
IL_0018: ldarg.0
IL_0019: conv.i4
IL_001a: stloc.0
IL_001b: ldarg.0
IL_001c: ldloc.0
IL_001d: conv.r8
IL_001e: sub
IL_001f: stloc.1
IL_0020: ldloc.1
IL_0021: ldc.r8 0.5
IL_002a: bgt.s IL_003d
IL_002c: ldloc.1
IL_002d: ldc.r8 0.5
IL_0036: bne.un.s IL_0041
IL_0038: ldloc.0
IL_0039: ldc.i4.1
IL_003a: and
IL_003b: brfalse.s IL_0041
IL_003d: ldloc.0
IL_003e: ldc.i4.1
IL_003f: add
IL_0040: stloc.0
IL_0041: ldloc.0
IL_0042: ret
IL_0043: ldarg.0
IL_0044: ldc.r8 -2147483648.5
IL_004d: blt.un.s IL_007a
IL_004f: ldarg.0
IL_0050: conv.i4
IL_0051: stloc.2
IL_0052: ldarg.0
IL_0053: ldloc.2
IL_0054: conv.r8
IL_0055: sub
IL_0056: stloc.3
IL_0057: ldloc.3
IL_0058: ldc.r8 -0.5
IL_0061: blt.s IL_0074
IL_0063: ldloc.3
IL_0064: ldc.r8 -0.5
IL_006d: bne.un.s IL_0078
IL_006f: ldloc.2
IL_0070: ldc.i4.1
IL_0071: and
IL_0072: brfalse.s IL_0078
IL_0074: ldloc.2
IL_0075: ldc.i4.1
IL_0076: sub
IL_0077: stloc.2
IL_0078: ldloc.2
IL_0079: ret
IL_007a: ldstr "Overflow_Int32"
IL_007f: call string System.Environment::GetResourceString(string)
IL_0084: newobj instance void System.OverflowException::.ctor(string)
IL_0089: throw
<----------


You see the difference between what's required and what's done? :-)
 
runningOnEmpty submitted this idea :

Not if you have option strict on.

Fair enough, given that cint seems a throwback to vb6 then:

Dim i As Integer = CType(Math.Truncate(d), integer) '?
 
Armin Zingler explained on 1/10/2011 :
Am 11.01.2011 01:36, schrieb Tom Shelton:

CInt perform rounding. That's what I want to avoid because it's unnecessary
and costs time. It's unnecessary because Truncate has been called before.

I realize that, but there is no direct way that I know of in VB. If
you have option strict on, that is...
 
runningOnEmpty brought next idea :
Fair enough, given that cint seems a throwback to vb6 then:

Dim i As Integer = CType(Math.Truncate(d), integer) '?

That just converts to essentially what I had, when you get to the il.
No reason not to use CInt - since that's what you mean.
 
Am 11.01.2011 01:55, schrieb runningOnEmpty:
Works without the CInt function, it seems redundant here.


Neither CInt nor Truncate is redundant:

- Only Math.Truncate() wouldn't work because of a type mismatch.
Do you know which kind of conversion is done internally if
Option Strict is Off? I do not. Therefore, Option Strict On makes
you think about it and convert as intended.

- Only CInt() gives not the same results as CInt(Math.Truncate()),
e.g. CInt(0.6) = 1 whereas CInt(Math.Truncate(0.6)) is 0.


I'm currently at a little tool showing the differences in a table.
(because I'm unable to remember...) I've just added the Truncate function:

http://www.abload.de/image.php?img=double2integerfunction1ncm.png

The first column is the value to be converted.

For each line the rules are:
- Same background color = same data type
- Same foreground color = same value

(the exe also shows negative values not shown in the screenshot)
 
Am 11.01.2011 02:17, schrieb Tom Shelton:
I realize that, but there is no direct way that I know of in VB. If
you have option strict on, that is...

Yes, not in VB, but obviously not in the Framework, too. Such a simple task... ^^
Anyway, thanks.
 
Am 11.01.2011 02:13, schrieb runningOnEmpty:
Fair enough, given that cint seems a throwback to vb6 then:

Dim i As Integer = CType(Math.Truncate(d), integer) '?

CType(double , Integer) is the same as CInt (double).

Why "throwback"? Anyway, if you meant to leave out Math.Truncate
(not leave out Cint), I don't see a problem even with Strict On.
 
Am 11.01.2011 02:13, schrieb runningOnEmpty:
Fair enough, given that cint seems a throwback to vb6 then:

Dim i As Integer = CType(Math.Truncate(d), integer) '?

BTW, with Option Strict Off, Math.Round(d) is called, followed
by a conversion to Integer:

Dim d As Double = 7.9999R
Dim i As Integer = d


IL code:

IL_0009: ldc.r8 7.9999000000000002
IL_0012: stloc.0
IL_0013: ldloc.0
IL_0014: call float64 [mscorlib]System.Math::Round(float64)
IL_0019: conv.ovf.i4
IL_001a: stloc.1
 
Here you go:

Dim d As Double = 7.9999999
Dim i As Integer = CInt(Int(d))

Console.WriteLine(i)

Output:

7

Int() function returns the same data type as the input, so it's necessary to
use CInt() to convert it to Integer.
 
Armin Zingler explained on 1/10/2011 :

I realize that, but there is no direct way that I know of in VB. If you
have option strict on, that is...

I may be misreading this, in my test in VS2008 with strict on both CInt
and CType return the whole part of the double without any rounding.
 
runningOnEmpty said:
I may be misreading this, in my test in VS2008 with strict on both CInt
and CType return the whole part of the double without any rounding.

No, it rounds, example:

Dim d As Double = 7.9999999
Dim i As Integer = CInt(d)

Console.WriteLine(i)

Output:

8
 
Am 11.01.2011 02:40, schrieb Nobody:
Here you go:

Dim d As Double = 7.9999999
Dim i As Integer = CInt(Int(d))

Console.WriteLine(i)

Output:

7

Int() function returns the same data type as the input, so it's necessary to
use CInt() to convert it to Integer.

Thank you, but as I underlined it in my first post, I want to convert to Integer
without rounding. CInt does perform rounding. Rounding is unnecessary after
calling Int().
 
Back
Top