Does a String contain a Float?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Does a String contain a Float?

Mikael Svane
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


Reply | Threaded
Open this post in threaded view
|

Re: Does a String contain a Float?

Ian Bartholomew-18
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.


Reply | Threaded
Open this post in threaded view
|

Re: Does a String contain a Float?

Bill Schwab-2
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]


Reply | Threaded
Open this post in threaded view
|

Re: Does a String contain a Float?

Mikael Svane
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