What is the best way to check if a String contains (only) a Float in
Smalltalk syntax (using $. as decimal point)? Should I base the method on Number>>readSmalltalkRealFrom:initialInteger: or is there a better approach? Best regards, Mikael Svane |
Mikael,
> What is the best way to check if a String contains (only) a Float in > Smalltalk syntax (using $. as decimal point)? Should I base the > method on Number>>readSmalltalkRealFrom:initialInteger: or is there a > better approach? I would say that it depends on how restrictive to want to be - what do you consider a valid Float in your context. If it's wide then just do something like (Number fromString: aString) asFloat and trap any exceptions. If you want to be very restrictive, only floats in the format 'abc.def' for example, then a simple check on the characters and format would probably be easier... isValid: aString ^(aString allSatisfy: [:each | '0123456789.' includes: each]) and: [aString first ~= $. and: [aString last ~= $. and: [whatever]]]] -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
Mikael,
I hesitate to describe what follows as the "best way", but it appears to serve. I also have a mutation of the type converter herein that obviously tries to treat blanks and nils a little carefully, but it is not as well tested (and hopefully obsolete by now). Feel free to use or ignore this as you see fit. If you want the other converter, you are welcome to it, but you've been warned :) Have a good one, Bill ========================== NumberToText subclass: #FloatToTextWKS instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: ''! FloatToTextWKS guid: (GUID fromString: '{96DF2961-0ABA-11D5-8596-0000B49D2CF2}')! FloatToTextWKS comment: ''! !FloatToTextWKS categoriesForClass!Unclassified! ! !FloatToTextWKS methodsFor! leftToRight: aNumber "Answers the result of converting aNumber to a String" | out | out := String writeStream. aNumber asFloat printOn:out decimalPlaces:3. ^out contents ! ! !FloatToTextWKS categoriesFor: #leftToRight:!operations!public! ! !FloatToTextWKS methodsFor! rightToLeft: aString "Answers the result of converting aString to a Number." ^Float fromStringWKS: aString! ! !FloatToTextWKS categoriesFor: #rightToLeft:!operations!public! ! !Float class methodsFor! fromStringWKS:aString "Instantiate a new instance of the receiver from the <readableString> argument. 4.01.3 threw us a curve, so hack around numbers such as '.4'. D5 also fails, this time on trailing decimal such as '4.'." | negate in out text | out := String writeStream. aString notEmpty ifTrue:[ "There should be at most one decimal point" ( aString select:[ :each | each = $. ] ) size <= 1 ifFalse:[ InvalidFormat signalWith:aString. ]. in := aString readStream. "Note whether or not we are reading a negative number" negate := in peekFor:$-. "Given a 'leading' decimal point, prepend a zero, and be sure to add the decimal point consumed by #peekFor:" ( in peekFor:$. ) ifTrue:[ out nextPutAll:'0.'. ]. "Transfer the remaining text" out nextPutAll:in upToEnd. ]. text := out contents. text notEmpty ifTrue:[ ( text last = $. ) ifTrue:[ text := text copyFrom:1 to:text size - 1. ]. ]. ^negate ifTrue:[ ( self fromString:text ) negated. ] ifFalse:[ self fromString:text ]. " | text | text := aString. ( text notEmpty and:[ text first = $. ] ) ifTrue:[ text := '0', aString. ]. ^self fromString:text " ! ! !Float class categoriesFor: #fromStringWKS:!instance creation!public! ! TestCase subclass: #FloatToTextWKSTest instanceVariableNames: 'typeConverter' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: ''! FloatToTextWKSTest guid: (GUID fromString: '{E240CBBC-1335-11D6-8596-0000B49D2CF2}')! FloatToTextWKSTest comment: ''! !FloatToTextWKSTest categoriesForClass!Unclassified! ! !FloatToTextWKSTest methodsFor! setUp "Prepare state for tests" typeConverter := FloatToTextWKS new. ! ! !FloatToTextWKSTest categoriesFor: #setUp!public!Running! ! !FloatToTextWKSTest methodsFor! testDecimalOnly "Converting one digit at a time, we have to tolerate '.' on the way to stuff like '.4'." self should:[ ( typeConverter rightToLeft:'.' ) = 0.0 ]. self should:[ ( typeConverter rightToLeft:'-.' ) = 0.0 ]. ! ! !FloatToTextWKSTest categoriesFor: #testDecimalOnly!public!Testing! ! !FloatToTextWKSTest methodsFor! testNoLeadingZero "Users often type .4 vs. 0.4; the machine needs to adapt." self should:[ ( typeConverter rightToLeft:'.' ) = 0.0 ]. self should:[ ( typeConverter rightToLeft:'.4' ) = 0.4 ]. ! ! !FloatToTextWKSTest categoriesFor: #testNoLeadingZero!public!Testing! ! !FloatToTextWKSTest methodsFor! testTrailingDecimal "Converting one digit at a time, we have to tolerate input such as '45.'." self should:[ ( typeConverter rightToLeft:'4.' ) = 4.0 ]. ! ! !FloatToTextWKSTest categoriesFor: #testTrailingDecimal!public!Testing! ! !FloatToTextWKSTest methodsFor! testNegativeNumbers "Users often type .4 vs. 0.4; they are in the wrong, but the machine needs to adapt. Here we look at -0.4, -.4, etc." self should:[ ( typeConverter rightToLeft:'-' ) = 0.0 ]. self should:[ ( typeConverter rightToLeft:'-0.4' ) = - 0.4 ]. self should:[ ( typeConverter rightToLeft:'-.4' ) = - 0.4 ]. self should:[ ( typeConverter rightToLeft:'-4' ) = - 4.0 ]. ! ! !FloatToTextWKSTest categoriesFor: #testNegativeNumbers!public!Testing! ! !FloatToTextWKSTest methodsFor! testInvalidFormats self should:[ typeConverter rightToLeft:'3.22.5'. ] raise:InvalidFormat. "12-03 - should Float class>>fromString: raise invalid format vs. Error?" self should:[ typeConverter rightToLeft:'--'. ] raise:Error. ! ! !FloatToTextWKSTest categoriesFor: #testInvalidFormats!public! ! -- Wilhelm K. Schwab, Ph.D. [hidden email] |
Bill and Ian,
thanks for your solutions. In this case, I choose Ian's #isValid: approach (replacing [whatever] with [aString occurrencesOf: $. = 1]). Best regards, Mikael Svane |
Free forum by Nabble | Edit this page |