# Thread: [RESOLVED] How to fast split Number integet part and decimal part ?

1. ## [RESOLVED] How to fast split Number integet part and decimal part ?

Code:
```Private Sub Form_Load()

Const s = 12345.6789

Dim w As Long
Dim k As Long
Dim p As Long

Dim integet_part   As Long
Dim decimal_part   As Double
Dim decimal_length As Long

'methode_01
integet_part = CLng(Split(s, ".")(0))
decimal_part = CLng(Split(s, ".")(1))
'================

'methode_02
str_001\$ = s
p = InStr(1, str_001, ".")
integet_part = CLng(Left\$(str_001, p - 1))
integet_part = CLng(Mid\$(str_001, p + 1))

' Prohibit use string and string function to get integet part and decimal part
' because it is too slow use string and string function
'
'

'methode_03
Const test_speed_loops = 10 ^ 6

TT = Timer

For k = 1 To test_speed_loops  'still too slow, because CDec() too slow

integet_part = Int(s)
decimal_part = CDec(s) - Int(s)

For w = 1 To 10 ^ 9
decimal_part = decimal_part * 10
If (decimal_part - Int(decimal_part)) = 0 Then
'MsgBox w, , "decimal lenght"
decimal_length = w
Exit For
End If
Next

Next

MsgBox Timer - TT

End

End Sub```

2. ## Re: How to fast split Number integet part and decimal part ?

My first thought would be to do something like this:

Code:
```
Dim integer_part   As Double
Dim decimal_part   As Double
'
Dim d As Double
d = 12345.6789

integer_part = Fix(d)
decimal_part = d - integer_part

Debug.Print integer_part
Debug.Print decimal_part
```
And, a few comments. First, if we declare integer_part as a Double, we solve a few different problems. For one, it'll be faster because assigning to a Double won't require any typecasting. Second, if our original number is larger than a Long, we won't overflow it.

And then also, if we stick with math (rather than using strings and the Instr function), things will clearly be much faster, as everything will be done in the IEEE floating-point-processor, which is much faster than dealing with Strings.

Also, having the input argument as a regular variable, rather than a Const, will also probably be faster. When passing constants, VB6 creates a temporary variable to protect the constant, where that's not going to happen with a regular variable.

However, I'll let you do your speed testing.

Good Luck,
Elroy

3. ## Re: How to fast split Number integet part and decimal part ?

@Elroy...that's interesting (Sorry to butt in).

When I ran your snippet, my decimal_part shown in debug.print was: 0.678900000000795

Why would that be? Where did those 8 extra zeroes followed by 795 come from?

4. ## Re: How to fast split Number integet part and decimal part ?

Hi @all,

my 2 cents..

Code:
```Private Sub Command10_Click()
Dim Trennzeichen As String
Trennzeichen = "."

Dim Parts() As String
Dim Satz As String

Satz = "12345.6789"

Parts() = Split(Satz, Trennzeichen)

MsgBox Parts(0)
MsgBox Parts(1)

End Sub```
regards
Chris

5. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by SamOscarBrown
@Elroy...that's interesting (Sorry to butt in).

When I ran your snippet, my decimal_part shown in debug.print was: 0.678900000000795

Why would that be? Where did those 8 extra zeroes followed by 795 come from?

so you need use

decimal_part = Cdec(d) - integer_part

but Cdec() is a slow function

6. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by Elroy
My first thought would be to do something like this:

For one, it'll be faster because assigning to a Double won't require any typecasting

Elroy

because really time consuming is Cdec() function and code For w = 1 To 10 ^ 9 .... Next

7. ## Re: How to fast split Number integet part and decimal part ?

Why are you using CDec? That converts to Decimal type, which you don't want to use.
Not only is the Decimal type very slow - you're not even storing it in a Decimal, you're doing a second conversion back to Double.
Do as Elroy suggested and just keep them as Double.

8. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by DEXWERX
Why are you using CDec? That converts to Decimal type, which you don't want to use.
Not only is the Decimal type very slow - you're not even storing it in a Decimal, you're doing a second conversion back to Double.
Do as Elroy suggested and just keep them as Double.

=============================

9. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by SamOscarBrown
@Elroy...that's interesting (Sorry to butt in).

When I ran your snippet, my decimal_part shown in debug.print was: 0.678900000000795

Why would that be? Where did those 8 extra zeroes followed by 795 come from?
Such is the life of a Base 10 fraction being crammed into a base 2 format.
They can only be so accurate.

If you don't like it you can either use a more accurate format, (doesn't have to be base 2)
or round it.

10. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by SamOscarBrown
@Elroy...that's interesting (Sorry to butt in).

When I ran your snippet, my decimal_part shown in debug.print was: 0.678900000000795

Why would that be? Where did those 8 extra zeroes followed by 795 come from?
The problem of storing fractions in a binary notation.
Code:
```Debug.Print 12345.6789 - 12345
-> 0.678900000000795```

11. ## Re: How to fast split Number integet part and decimal part ?

Such is the life of a Base 10 fraction being crammed into a base 2 format.
They can only be so accurate.
Thanks D....'such IS the life'. Fortunately, I don't have to deal with this type of accuracy in any of my 'home' projects. Appreciate the explanation. (yeah, if I were to WANT just the first four digits in the decimal, I'd use rounding).

Outa here!

12. ## Re: How to fast split Number integet part and decimal part ?

@quickbbb

I see, you're using the Decimal Format so you can get rid of the perceived inaccuracies of the Double format.
Why those inaccuracies exist, and how to deal with them is typically taught in computer science, but If you google it there are lots of resources explanations.

What's more important is deciding what kind of accuracy you need. How many digits?

Code:
```    Dim integer_part   As Double
Dim decimal_part   As Double
'
Dim d As Double
d = 12345.6789

integer_part = Fix(d)
decimal_part = d - integer_part

Debug.Print integer_part
Debug.Print Round(decimal_part, 4)```

13. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by DEXWERX
round it.
const decimal_part_length = 3

you mean round ( 123.456 , decimal_part_length ) ??

but you can not know in advance the decimal part length

d may be = 123.456789
d may be = 123.456
d may be = 123.4561111111

14. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by SamOscarBrown
@Elroy...that's interesting (Sorry to butt in).

When I ran your snippet, my decimal_part shown in debug.print was: 0.678900000000795

Why would that be? Where did those 8 extra zeroes followed by 795 come from?
Hi Sam,

That ...795 is just an artifact of converting binary to base-10 (i.e., decimal) and vice-versa. There's not really a "quick" way around that. Also, please notice that 0.678900000000795 is extremely close to 0.6789. In fact, in base-2, it's going to be as close as you can get.

And, for a general purpose algorithm (i.e., one that will work with any Double), that's going to be about as fast as you can get.

Now, if quickbbbb would like to provide some more restriction criteria, such as possibly the integer portion never overflowing a Long, or the fraction portion never has more than four digits, then we can possibly be a bit more accurate (however, pretty much anything is going to sacrifice speed, which is what I thought the whole point was). Any kind of typecasting (which my approach doesn't do) is going to slow things down.

Best To All,
Elroy

15. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by quickbbbb
const decimal_part_length = 3

you mean round ( 123.456 , decimal_part_length ) ??

but you can not know in advance the decimal part length
in engineering, you always do. In engineering only so many decimals matter...

If you need accuracy beyond what a Double can do - you have to sacrifice speed. Decimal is also a binary format, and similarly has only so much accuracy. If you want unlimited accuracy - you have to use a String Math Library/Big Number Library, or similar arbitrary precision math. Again - using anything like these, will be at a severe performance penalty.
https://en.wikipedia.org/wiki/Arbitr...ion_arithmetic

If you use the built in help, it can explain each datatype, min/max/epsilon, how many digits they are accurate to.

Originally Posted by MSDN
Decimal variables are stored as 96-bit (12-byte) signed integers scaled by a variable power of 10. The power of 10 scaling factor specifies the number of digits to the right of the decimal point, and ranges from 0 to 28. With a scale of 0 (no decimal places), the largest possible value is +/-79,228,162,514,264,337,593,543,950,335. With a 28 decimal places, the largest value is +/-7.9228162514264337593543950335 and the smallest, non-zero value is +/-0.0000000000000000000000000001.

How Many Decimals of PI do we really need?

https://www.jpl.nasa.gov/edu/news/20...e-really-need/

16. ## Re: How to fast split Number integet part and decimal part ?

And quickbbbb,

Just FYI, Decimal types are very strange animals. They're 14 bytes with 12 of those bytes being a mixed-endian unsigned mantissa, which means that nothing about them will be able to use the floating-point-processor (i.e., all math done in software). Also, because of what Microsoft tried to do with them (i.e., have a number that never loses any precision, even in the fractional part), a Double (or even a Single) can easily overflow them. Basically, they're a number from 0 to 79228162514264337593543950336 (i.e., 2^96) with a decimal point placed anywhere in that number (or on either end), and also a separate sign-bit.

Take Care,
Elroy

17. ## Re: How to fast split Number integet part and decimal part ?

Const s = 12345.6789

Const test_speed_loops = 10 ^ 6

TT = Timer

For k = 1 To test_speed_loops

aaaa\$ = cstr(s)

Next

MsgBox Timer - TT '----> it cost 0.29 second

my code split integet part and decimal part need 0.8 second

when VBA.Cstr( ) convert floating point to String , it same need calculate integet part length and decimal part length

but VBA.Cstr( ) can calculate it very fast

it should mean really can be split integet part and decimal part very fast . just VBA not offered a function to calculate decimal part length

18. ## Re: How to fast split Number integet part and decimal part ?

Elroy offered a solution to calculate decimal part, that's faster than Cstr()?

You're making a mountain out of a mole hill.

19. ## Re: How to fast split Number integet part and decimal part ?

You can test this if you like, it should be faster than converting with CDec. However, conversion to Double is used to handle wide range of values and string manipulation used to return unaltered fractional part of the number, locale-aware.

Code:
```Public Sub SplitNumber(theNumber As Double, rtnWholeNr As Double, rtnFraction As Double)

rtnWholeNr = Int(theNumber)
If rtnWholeNr = theNumber Then
rtnFraction = 0
Else
rtnFraction = CDbl("0" & Mid\$(CStr(theNumber), Len(CStr(rtnWholeNr)) + 1))
End If

End Sub```
Sample Call:
Code:
```Dim dblWhole As Double, dblFraction as Double
SplitNumber 12345.6789, dblWhole, dblFraction```

20. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by DEXWERX
Elroy offered a solution to calculate decimal part, that's faster than Cstr()?

You're making a mountain out of a mole hill.

my data amount very huge , i need a function faster than cstr()

vba.Cstr convert long type to String = 4 second
My.Cstr convert long type to String = 2 second

now i need let My.Cstr can convert float type to String faster than vba.Cstr
so i need know decimal part length

Originally Posted by LaVolpe
You can test this if you like, it should be faster than converting with CDec. However, conversion to Double is used to handle wide range of values and string manipulation used to return unaltered fractional part of the number, locale-aware.

Code:
```Public Sub SplitNumber(theNumber As Double, rtnWholeNr As Double, rtnFraction As Double)

you code = 1.4 second
my code  = 0.8 second

rtnWholeNr = Int(theNumber)
If rtnWholeNr = theNumber Then
rtnFraction = 0
Else
rtnFraction = CDbl("0" & Mid\$(CStr(theNumber), Len(CStr(rtnWholeNr)) + 1))
End If

End Sub```
Sample Call:
Code:
```Dim dblWhole As Double, dblFraction as Double
SplitNumber 12345.6789, dblWhole, dblFraction```

my code = 0.8 secomd

21. ## Re: How to fast split Number integet part and decimal part ?

Say LaVolpe,

Isn't that Int() going to do funky things to negative numbers? That's why I used Fix(). I'll admit though that your approach does a better job of not adding superfluous fractional numbers. All the typecasting is sure going to slow things down though. But, at this point, I'm very confused about what quickbbbb's ultimate objective is.

Y'all Take Care,
Elroy

22. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by quickbbbb
my data amount very huge , i need a function faster than cstr()
Then quickbbbb, I gave you the answer in post #2. I suppose you could declare the fractional part as a Single. That would clean up most of your "very small" artifacts. And typecasting from Double to Single will be much faster than doing anything that involves typecasting to a String.

Good Luck,
Elroy

23. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by Elroy
Say LaVolpe,

Isn't that Int() going to do funky things to negative numbers? That's why I used Fix(). I'll admit though that your approach does a better job of not adding superfluous fractional numbers. All the typecasting is sure going to slow things down though. But, at this point, I'm very confused about what quickbbbb's ultimate objective is.

Y'all Take Care,
Elroy
Good point. Int() can round up negative numbers. And type-casting will slow things down, no doubt.

And as you said, we don't really know what the point is. Why the need to separate a fractional part from the whole & keep the fraction separately? If the range of numbers were known (i.e., none exceed min/max of Single for example), more efficiencies might be made. Turning off overflow checks could be helpful too.

24. ## Re: How to fast split Number integet part and decimal part ?

use int() function is my Negligence

my data amount very huge , i need a function faster than cstr()

vba.Cstr convert long type to String = 4 second
My.Cstr convert long type to String = 2 second

now i need let My.Cstr can convert float type to String faster than vba.Cstr
so i need know decimal part length

25. ## Re: How to fast split Number integet part and decimal part ?

VBA.Fix( ) has bug

sometime I use Fix() to get value , it return a round value

26. ## Re: How to fast split Number integet part and decimal part ?

If the whole point is to convert a number to a string faster than CStr() I believe Olaf posted a faster CStr()

But honestly - none of what you're doing makes any sense. What's the purpose of converting a large amount of numbers to string?

First you're issue was with the speed of CDec(),
Then it was the accuracy of the Double type.
Now its the speed of CStr().

It would be good to know the goal - because it seems you don't know the best way to it. We could help if we knew what the goal was.

27. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by DEXWERX
It would be good to know the goal - because it seems you don't know the best way to it. We could help if we knew what the goal was.
Dex, sounds something like this:

1. He has his own CStr() routine for Long to String that he says is 2x faster than CStr()

2. Sounds like he is looking at a way to separate the numbers into whole/fraction parts so he can then use his own CStr() implementation? And the separation is what he is wanting as fast as possible.

But I'm not sure how that 2nd part is going to work. Wouldn't the fractional part need to be stored in a Single or Double to preserve any leading zeroes? And if so, stripping a part of a double to be placed in another double, then putting that into a string, doesn't sound like it's going to be speedy regardless

28. ## Re: How to fast split Number integet part and decimal part ?

quickbbbb, one thing you must understand ... if you're going to insist on converting to a string, that's going to be slow. All numbers (true numeric variables or constants) are some kind of binary in VB (VB6 and/or VBA). And floating-point (which would include Single, Double, & Decimal) can be even more complex.

And Strings are basically arrays of characters, and, inherently, have nothing to do with numbers. And any algorithm to convert these binary floating-point numbers into strings is going to be slow. You may be able to "roll-your-own" and speed it up a bit, as I suspect the CStr() function does checking to see if it should go to scientific notation, and some other checking (possibly for NaN and Inf), where a roll-your-own wouldn't need to do that. But it's still not going to be super-speedy.

And also, just thinking it through, if we insisted on this approach, and a Decimal type would cover our range of numbers, I suspect a CnvDecToStr() function could probably be optimized to be fastest (faster than CnvSngToStr() or CnvDblToStr()). I say this because these Decimal types are basically 96 bit integers with an inserted decimal point. I'd have to ponder the fastest way to get this 96 bit integer into a String. I might even consider going through a LongLong to get it done (which VB6 can be forced to handle and new VBA versions just have). I wonder how fast a CStr(LongLong) would be? If it's very fast, that might be an answer. Just do that, and then insert the decimal point and any minus sign.

However, I'm just spit-balling. As Dex said a few posts up, it seems like you're making a mountain out of a mole-hill.

Good Luck,
Elroy

EDIT1: Actually, if we want to be sure and handle the full range of a Decimal, we can't put the integer in a LongLong, as the integer portion of a decimal is 12 bytes, and a LongLong is only 8 bytes. But quickbbbb, in post #1, is putting the integer portion in a Long, which is only 4 bytes. So we really do need better criteria for what we're trying to do before an appropriate answer can be offered. quickbbbb, what's the range of numbers you need to deal with (both in terms of magnitude and in terms of fractional precision)?

29. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by Elroy

if you're going to insist on converting to a string, that's going to be slow
Elroy
after i get stock price ( float type ) , i need save stock price to file

so I need convert number to string

of course , i can save it to Binary file ( it will be no need to convert to string )

but For some reason , I must save it to text file

30. ## Re: How to fast split Number integet part and decimal part ?

Excellent. That helps tremendously.

quickbbbb, tell me if I'm wrong, but don't stock prices consider splitting once they get very much over \$1000? And also, wouldn't four decimal places be the maximum you'd ever track regarding stock prices?

If all that's true, then I'd consider using a Currency (especially if the max four decimal places can be assumed). You could trivially, do everything you want while keeping all types as Currency.

Code:
```
Const s As Currency = 12345.6789

Dim integer_part   As Currency
Dim decimal_part   As Currency

integer_part = Fix(s)
decimal_part = s - integer_part

Debug.Print integer_part
Debug.Print decimal_part

```
Take Care,
Elroy

EDIT1: And Currency math is effectively a special form of integer math, which is lightening fast.

31. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by DEXWERX
If the whole point is to convert a number to a string faster than CStr() I believe Olaf posted a faster CStr()
Is it possible to provide a URL?

thank you

32. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by Elroy
Excellent. That helps tremendously.

quickbbbb, tell me if I'm wrong, but don't stock prices consider splitting once they get very much over \$1000? And also, wouldn't four decimal places be the maximum you'd ever track regarding stock prices?
You shouldn't assume it will be stock prices from a USA Market. Also, see Berkshire Hathaway A stock.

33. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by OptionBase1
You shouldn't assume it will be stock prices from a USA Market. Also, see Berkshire Hathaway A stock.
Hi Option,

Well yeah, I knew they were sort of doing away with all the splitting. However, so long as we're good with four decimal places, Currency seems like the correct choice. That might get a bit tight form some currencies that use three decimal places and want to track stocks to 1/100th of a penny, but I don't think most (if any) of those places have stock exchanges. Does Chile have a stock exchange, or Bahrain? Again, I suppose we need more specifics from quickbbbb, but I'm thinking that Currency would get the job done. I mean, look at the name of the type, and then think about what we're trying to do.

Take Care,
Elroy

34. ## Re: How to fast split Number integet part and decimal part ?

Elroy:
I knew they were sort of doing away with all the splitting.
Not True.

Most items that are traded can be grouped into:
1) Indexes
2) Commodities
3) Stocks (large cap, medium cap, small cap)
4) Options
5) Bonds
6) Real Estate Trusts.

Within each on of these groups the number of significant digits can vary Not only based on their
calculated value (such as indexes), but the price EACH EXCHANGE sets (number of significant digits)
for the instrument. The same instrument may be traded on multiple exchanges.
Some trade in 1/8th, quarters, decimal values, etc. Go to the NYSE or (www.cmegroup.com) and pull up a few.
My recommendation is to set up a table by symbol and then associate the decimal value need for that instrument.
For example if trades in 1/8th use .125
Then based on the instrument of interest, you know what calculation is needed.

35. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by quickbbbb
...but For some reason , I must save it to text file
This seems to be the problem if this text file is for your use. Why should the format of the data in the file matter? Save it as binary or as a UDT record. If this text file is for use in some other application, then it is understandable that you don't have any say in the format. But if not, why force a file format that you say is slowing you down?

36. ## Re: How to fast split Number integet part and decimal part ?

And the FileIO will be the bottleneck, not the speed of a typical conversion routine.

37. ## Re: How to fast split Number integet part and decimal part ?

None of this thread makes a lot of sense to me. Is this some attempt to do battle with regional and language settings, i.e. the character used to represent decimal points?

38. ## Re: How to fast split Number integet part and decimal part ?

Hi quickbbbb,

Originally Posted by quickbbbb
my data amount very huge , i need a function faster than cstr()
you say your Data is very huge, it would be helpful to know where the Data comes from and in what Format
why do you want to split the number anyway ?

regards
Chris

39. ## Re: How to fast split Number integet part and decimal part ?

Originally Posted by ChrisE
...
why do you want to split the number anyway ?
...
Chris
LaVolpe already explained a probable reason in post #27, and also identified a possible situation quickbbbb didn't consider, i.e. leading 0's in the decimal portion.

40. ## Re: How to fast split Number integet part and decimal part ?

Now I decided to accelerate it with multi cpu core

Originally Posted by dilettante
None of this thread makes a lot of sense to me. Is this some attempt to do battle with regional and language settings, i.e. the character used to represent decimal points?

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

Featured