Jump to content

Shape-Machine

From Rosetta Code
Shape-Machine is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Task:

Get user input (or store the number somewhere if the programing langauge doesn't support input) and then add 3, multiply that 0.86 and repeat that over and over again.

Optionally, halt the loop when quiescence has been achieved, i.e. when the value does not change, and report that value and the corresponding number of iterations.

See Also

ALGOL 68

Non-terminating

Translation of: Python
BEGIN
    REAL a := BEGIN INT n; read( n ); n END;
    DO
        print( ( fixed( a +:= 3 *:= 0.86, -16, 14 ), newline ) )
    OD
END

Terminating after successive values converge

Based on Raku, using 64-bit floating point (assuming REAL is 64-bit in the implementation you are using - which is very likely these days and true for Algol 68G).

BEGIN
    REAL a      := BEGIN INT n; read( n ); n END;
    REAL prev a := IF a = 0 THEN 1 ELSE 0 FI;
    INT  count  := 0;
    WHILE prev a /= a
    DO
        count +:= 1;
        prev a := a;
        print( ( fixed( a +:= 3 *:= 0.86, -16, 14 ), newline ) )
    OD;
    print( ( whole( count, 0 ), " repetitions" ) )
END
Output:

With 4 as the input

6.02000000000000
7.75720000000000
9.25119200000000
10.5360251200000
11.6409816032000
12.5912441787520
13.4084699937267
14.1112841946050
...
18.3988095846536
18.4029762428021
18.4065595688098
...
18.4285714285714
18.4285714285714
18.4285714285714
231 repetitions

32-bit terminating

If you have an implementation of Algol 68 where SHORT REAL is 32-bit, here's a version that would converge faster to a less precise value. Note that in Algol 68G, both REAL and SHORT REAL are 64-bit. Interestingly, the final value appears to converge to slightly different values depending on the input - presumably because 32-bit floats are more limited in precision.

BEGIN
    INT n; read( ( n, newline ) );
    SHORT REAL a      := n;
    SHORT REAL prev a := IF a = 0 THEN 1 ELSE 0 FI;
    INT  count  := 0;
    WHILE prev a /= a
    DO
        count +:= 1;
        prev a := a;
        print( ( fixed( a +:= 3 *:= 0.86, -9, 5 ), newline ) )
    OD;
    print( ( whole( count, 0 ), " repetitions" ) )
END
Output:

With 451 as the input value

390.44000
338.35840
293.56824
...
 18.42858
 18.42858
 18.42858
120 repetitions

With 4 as the input value

  6.02000
  7.75720
  9.25119
 10.53603
 11.64098
...
 18.42857
 18.42857
 18.42857
97 repetitions

ALGOL W

Translation of: Python
begin
    real a;
    integer n;
    read( n );
    a := n;
    while true do begin
        a := a + 3;
        a := a * 0.86;
        write( r_format := "A", r_w := 8, r_d := 5, a )
    end
end.
Output:

With 4 as the input

 6.02000
 7.75720
 9.25119
10.53603
11.64098
12.59124
13.40847
14.11128
...
18.42857
18.42857
18.42857
...

BASIC

Works with: BBC BASIC
Works with: Atari BASIC
Works with: ProgressBASIC

NOTE FROM THE CREATOR OF THE TASK:i haven't tested this code on other interpriters of BASIC. Also $ is not in the PBASIC keyboard of PB95 8-bit computers

10 INPUT I$
20 LET I = I + 3
30 LET I = I * 0.86
40 PRINT I
50 GOTO 20

ANSI BASIC

Translation of: FreeBASIC
Works with: Decimal BASIC
100 REM Shape-Machine
110 LET Cnt = 1
120 INPUT Prev
130 DO
140    LET Sgte = (Prev + 3) * 0.86
150    IF Prev = Sgte THEN EXIT DO
160    PRINT Sgte
170    LET Prev = Sgte
180    LET Cnt = Cnt + 1
190 LOOP
200 PRINT "Took"; Cnt; "iterations."
210 END
Output:

With 4 as the input.

 6.02 
 7.7572 
 9.251192 
 10.53602512 
 11.6409816032 
 12.591244178752 
 13.4084699937267 

...

 18.4285714285696 
 18.4285714285699 
 18.4285714285701 
 18.4285714285703 
 18.4285714285705 
 18.4285714285706 
 18.4285714285707 
 18.4285714285708 
 18.4285714285709 
 18.428571428571 
 18.4285714285711 
Took 208 iterations.                  

The output may vary depending on implementation.

Applesoft BASIC

10 INPUT "num:"; I : I = INT(I)
11 LET I = I + 3
12 LET I = I * 0.86
20 PRINT I
21 GOTO 11

BASIC256

input integer i
re: #
i += 3
i *= 0.86
? i
goto re

Chipmunk Basic

Translation of: FreeBASIC
Works with: Chipmunk Basic version 3.6.4
100 cls
110 cnt = 1
120 input prev
130 while 1
140   sgte = (prev+3)*0.86
150   if prev = sgte then exit while
160   print sgte
170   prev = sgte
180  cnt = cnt+1
190 wend
200 print "Took ";cnt;"iterations."
210 end

Commodore BASIC

Translation of: FreeBASIC
Works with: Commodore BASIC version 3.5
10 REM SHAPE-MACHINE
20 CNT%=1
30 INPUT PREV
40 DO
50 SGTE=(PREV+3)*0.86
60 IF PREV=SGTE THEN EXIT
70 PRINT SGTE
80 PREV=SGTE
90 CNT%=CNT%+1
100 LOOP
110 PRINT "TOOK";CNT%;"ITERATIONS."
120 END
Output:

With 4 as the input.

 6.02                                   
 7.75720001                             
 9.25119201                             
 10.5360251                             
 11.6409816                             
 12.5912442                             
 13.40847  

...

 18.4285713                             
 18.4285714                             
 18.4285714                             
 18.4285714                             
 18.4285714                             
 18.4285714                             
 18.4285714                             
 18.4285714                             
 18.4285714                             
 18.4285714                             
TOOK 134 ITERATIONS.                    

FreeBASIC

Dim As Double prev, sgte
Dim As Integer cnt = 1

Input " ", prev

Do
    sgte = (prev + 3) * 0.86
    If prev = sgte Then Exit Do
    Print sgte
    prev = sgte
    cnt += 1
Loop

Print !"\nTook"; cnt; " iterations."

Sleep
Output:

With 4 as the input

 6.02
 7.757199999999999
 9.251192
 10.53602512
 11.6409816032
 12.591244178752
 13.40846999372672
 14.11128419460498
 14.71570440736028
 ...
 18.42857142857134
 18.42857142857135
 18.42857142857136
 18.42857142857137
 18.42857142857138
 18.42857142857139
 18.4285714285714
 18.4285714285714
 18.42857142857141
 18.42857142857141
Took 227 iterations.

GW-BASIC

Works with: PC-BASIC version any
Works with: BASICA
Works with: QBasic
Works with: MSX BASIC version any

The MSX BASIC solution works without any changes.

Liberty BASIC

Translation of: FreeBASIC
Works with: Just BASIC
rem Shape-Machine
cnt = 1
input prev
sgte = (prev + 3) * 0.86
do while prev <> sgte
  print sgte
  prev = sgte
  cnt = cnt + 1
  sgte = (prev + 3) * 0.86
loop
print "Took "; cnt; " iterations."
end
Output:

With 4 as the input.

6.02
7.7572
9.251192
10.5360251
11.6409816
12.5912442
13.40847  

...

18.4285714
18.4285714
18.4285714
Took 231 iterations.

Minimal BASIC

Translation of: FreeBASIC
Works with: BASICA
10 REM Shape-Machine
20 LET C = 1
30 INPUT P
40 LET S = (P+3)*.86
50 IF P = S THEN 100
60 PRINT S
70 LET P = S
80 LET C = C+1
90 GOTO 40
100 PRINT "Took"; C; "iterations."
110 END

MSX Basic

Works with: MSX BASIC version any
Works with: Chipmunk Basic
Works with: GW-BASIC
10 cnt = 1
20 input prev
30 'while 1
40   sgte = (prev+3)*0.86
50   if prev = sgte then goto 100
60   print sgte
70   prev = sgte
80  cnt = cnt+1
90 goto 30
100 print "Took";cnt;"iterations."
110 end

OxygenBasic

Translation of: FreeBASIC
uses console

double prev, sgte
int cnt

cnt = 1
input() prev

do
    sgte = (prev + 3) * 0.86
    if prev = sgte then exit do
    printl sgte
    prev = sgte
    cnt ++ 
loop

printl cr "Took " cnt " iterations."

waitkey

PureBasic

Translation of: FreeBASIC
OpenConsole()

Define.d prev, sgte
Define.i cnt = 1
Define.s kbd$

kbd$ = Input()
prev = ValD(kbd$)

While #True
  sgte = (prev + 3) * 0.86
  If prev = sgte
    Break
  EndIf
  PrintN(StrD(sgte))
  prev = sgte
  cnt + 1
Wend

PrintN(#CRLF$ + "Took " + Str(cnt) + " iterations.")

PrintN(#CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()

QBasic

Works with: QBasic version 1.1
Works with: QuickBasic version 4.5
Works with: QB64
DIM prev AS DOUBLE, sgte  AS DOUBLE
DIM cnt AS INTEGER

cnt = 1
INPUT prev

sgte = (prev + 3) * .86
WHILE prev <> sgte
  PRINT sgte
  prev = sgte
  cnt = cnt + 1
  sgte = (prev + 3) * .86
WEND
PRINT "Took "; cnt; " iterations."
END

QB64

The QBasic solution works without any changes.

Quite BASIC

Translation of: Minimal BASIC
10 REM Shape-Machine
20 LET C = 1
30 INPUT ""; P
40 LET S = (P+3)*.86
50 IF P = S THEN 100
60 PRINT S
70 LET P = S
80 LET C = C+1
90 GOTO 40
100 PRINT "Took "; C; " iterations."
110 END

Run BASIC

Works with: Just BASIC
Works with: Liberty BASIC
rem Shape-Machine
cnt = 1
input prev
sgte = (prev + 3) * 0.86
while prev <> sgte
  print sgte
  prev = sgte
  cnt = cnt + 1
  sgte = (prev + 3) * 0.86
wend
print "Took "; cnt; " iterations."
end

True BASIC

Translation of: QBasic
LET cnt = 1
INPUT prev

LET sgte = (prev + 3) * .86
DO WHILE prev <> sgte
   PRINT sgte
   LET prev = sgte
   LET cnt = cnt + 1
   LET sgte = (prev + 3) * .86
LOOP
PRINT "Took "; cnt; " iterations."
END

XBasic

Works with: Windows XBasic
Translation of: FreeBASIC
PROGRAM	"Shape-Machine"
VERSION	"0.0000"

DECLARE FUNCTION  Entry ()

FUNCTION  Entry ()
    cnt& = 1

    kbd$ = INLINE$("")
    prev# = DOUBLE(kbd$)

    DO
        sgte# = (prev# + 3) * 0.86
        IF prev# = sgte# THEN EXIT DO
        PRINT sgte#
        prev# = sgte#
        INC cnt&
    LOOP

    PRINT "Took"; cnt&; " iterations."
END FUNCTION
END PROGRAM

Yabasic

c = 1

input " " prev

do
    sgte = (prev + 3) * 0.86
    if prev = sgte  break
    print sgte
    prev = sgte
    c = c + 1
loop

print "Took ", c, " iterations."
end
Output:
Same as FreeBASIC entry.

C++

#include <cstdint>
#include <iomanip>
#include <iostream>

int main() {
	double user_choice;
	std::cout << "Enter a number: ";
	std::cin >> user_choice;

	const double epsilon = 0.000'000'000'000'1;
	uint32_t iterations = 0;
	double previous = 0.0;
	double current = user_choice;

	while ( std::abs(current - previous) > epsilon ) {
		previous = current;
		current = ( current + 3.0 ) * 0.86;
		iterations++;
	}

	std::cout << user_choice << " converged to " << std::fixed << std::setprecision(12)
			  << current << " after " << iterations << " iterations." << std::endl;
}
Output:
Enter a number: -72
-72 converged to 18.428571428571 after 217 iterations.

DuckDB

Works with: DuckDB version V1.0

In the following, the way the functions are invoked will determine the precision of the computation, as illustrated by the two results shown.

To make it easy to write variations, a table-valued function is first defined:

create or replace function shape_machine_table(start, r) as table (
  with recursive cte as (
    select 0 as i, (start-1) as prev, start as x, 
    union all
    select i+1 as i,
           x as prev,
           (x+3) * r as x
    from cte
    where x != prev 
  )
  from cte
);

# Report the number of iterations required to achieve quiescence, and
# the value at quiescence:
create or replace function shape_machine_quiescence(start, r) as (
  select (last(i), last(x))
  from shape_machine_table(start, r)
);
.print FLOAT results:
select shape_machine_quiescence(0.0::FLOAT, 0.86);
.print DOUBLE results:
select shape_machine_quiescence(0.0::DOUBLE, 0.86);
Output:
FLOAT results:
┌────────────────────────────────────────────────────┐
│ shape_machine_quiescence(CAST(0.0 AS FLOAT), 0.86) │
│               struct(integer, float)               │
├────────────────────────────────────────────────────┤
│ (99, 18.428568)                                    │
└────────────────────────────────────────────────────┘

DOUBLE results:
┌─────────────────────────────────────────────────────┐
│ shape_machine_quiescence(CAST(0.0 AS DOUBLE), 0.86) │
│               struct(integer, double)               │
├─────────────────────────────────────────────────────┤
│ (233, 18.428571428571416)                           │
└─────────────────────────────────────────────────────┘

EasyLang

numfmt 15 0
n = 4
while n <> prev
   prev = n
   n = (n + 3) * 0.86
   cnt += 1
.
print n & " (after " & cnt & " iterations)"
Output:
18.428571428571416 (after 231 iterations)

FutureBasic

The results make better sense when the precision of the floats is carried to 15 decimal places for each iteration.

include "NSLog.incl"

begin globals
  double    nxt
  NSInteger cnt
end globals

local fn ShapeMachine( prv as double )
  while (YES)
    nxt = (prv + 3) * 0.86
    if prv == nxt
      NSLog( @"\n\tTook %d iterations.\n\n", cnt )
      exit fn
    end if
    NSLog( @"%3d. %.15f", cnt, nxt )
    prv = nxt
    cnt++
  wend
end fn

cnt = 1

fn ShapeMachine( 4 )

HandleEvents
Output:
  1. 6.020000000000000
  2. 7.757199999999999
  3. 9.251192000000000
  4. 10.536025120000000
  5. 11.640981603200000
  6. 12.591244178752000
  7. 13.408469993726719
  8. 14.111284194604979
  9. 14.715704407360279
 10. 15.235505790329839
 11. 15.682534979683661
 12. 16.066980082527948
 13. 16.397602870974033
 14. 16.681938469037668
 15. 16.926467083372394
 16. 17.136761691700258
 17. 17.317615054862223
 18. 17.473148947181510
 19. 17.606908094576099
 20. 17.721940961335445
 21. 17.820869226748481
 22. 17.905947535003694
 23. 17.979114880103175
 24. 18.042038796888729
 25. 18.096153365324305
 26. 18.142691894178903
 27. 18.182715028993854
 28. 18.217134924934715
 29. 18.246736035443856
 30. 18.272192990481717
 31. 18.294085971814276
 32. 18.312913935760278
 33. 18.329105984753838
 34. 18.343031146888300
 35. 18.355006786323937
 36. 18.365305836238587
 37. 18.374163019165184
 38. 18.381780196482058
 39. 18.388330968974568
 40. 18.393964633318127
 41. 18.398809584653588
 42. 18.402976242802087
 43. 18.406559568809794
 44. 18.409641229176422
 45. 18.412291457091722
 46. 18.414570653098881
 47. 18.416530761665037
 48. 18.418216455031931
 49. 18.419666151327462
 50. 18.420912890141619
 51. 18.421985085521790
 52. 18.422907173548740
 53. 18.423700169251916
 54. 18.424382145556649
 55. 18.424968645178719
 56. 18.425473034853699
 57. 18.425906809974180
 58. 18.426279856577793
 59. 18.426600676656900
 60. 18.426876581924933
 61. 18.427113860455442
 62. 18.427317919991680
 63. 18.427493411192845
 64. 18.427644333625846
 65. 18.427774126918226
 66. 18.427885749149674
 67. 18.427981744268720
 68. 18.428064300071100
 69. 18.428135298061147
 70. 18.428196356332585
 71. 18.428248866446022
 72. 18.428294025143579
 73. 18.428332861623478
 74. 18.428366260996189
 75. 18.428394984456723
 76. 18.428419686632783
 77. 18.428440930504191
 78. 18.428459200233604
 79. 18.428474912200898
 80. 18.428488424492773
 81. 18.428500045063785
 82. 18.428510038754855
 83. 18.428518633329176
 84. 18.428526024663093
 85. 18.428532381210260
 86. 18.428537847840822
 87. 18.428542549143106
 88. 18.428546592263071
 89. 18.428550069346240
 90. 18.428553059637768
 91. 18.428555631288479
 92. 18.428557842908091
 93. 18.428559744900959
 94. 18.428561380614823
 95. 18.428562787328747
 96. 18.428563997102721
 97. 18.428565037508339
 98. 18.428565932257172
 99. 18.428566701741168
100. 18.428567363497404
101. 18.428567932607766
102. 18.428568422042680
103. 18.428568842956704
104. 18.428569204942765
105. 18.428569516250779
106. 18.428569783975668
107. 18.428570014219073
108. 18.428570212228401
109. 18.428570382516423
110. 18.428570528964123
111. 18.428570654909144
112. 18.428570763221863
113. 18.428570856370801
114. 18.428570936478888
115. 18.428571005371843
116. 18.428571064619785
117. 18.428571115573014
118. 18.428571159392792
119. 18.428571197077801
120. 18.428571229486909
121. 18.428571257358740
122. 18.428571281328516
123. 18.428571301942522
124. 18.428571319670567
125. 18.428571334916686
126. 18.428571348028349
127. 18.428571359304382
128. 18.428571369001769
129. 18.428571377341520
130. 18.428571384513706
131. 18.428571390681785
132. 18.428571395986335
133. 18.428571400548247
134. 18.428571404471491
135. 18.428571407845482
136. 18.428571410747114
137. 18.428571413242519
138. 18.428571415388568
139. 18.428571417234167
140. 18.428571418821384
141. 18.428571420186390
142. 18.428571421360296
143. 18.428571422369853
144. 18.428571423238072
145. 18.428571423984742
146. 18.428571424626877
147. 18.428571425179115
148. 18.428571425654038
149. 18.428571426062472
150. 18.428571426413725
151. 18.428571426715802
152. 18.428571426975591
153. 18.428571427199007
154. 18.428571427391145
155. 18.428571427556385
156. 18.428571427698490
157. 18.428571427820700
158. 18.428571427925803
159. 18.428571428016191
160. 18.428571428093925
161. 18.428571428160776
162. 18.428571428218266
163. 18.428571428267709
164. 18.428571428310228
165. 18.428571428346796
166. 18.428571428378245
167. 18.428571428405291
168. 18.428571428428551
169. 18.428571428448553
170. 18.428571428465755
171. 18.428571428480549
172. 18.428571428493271
173. 18.428571428504213
174. 18.428571428513624
175. 18.428571428521717
176. 18.428571428528677
177. 18.428571428534664
178. 18.428571428539811
179. 18.428571428544238
180. 18.428571428548043
181. 18.428571428551315
182. 18.428571428554132
183. 18.428571428556552
184. 18.428571428558634
185. 18.428571428560424
186. 18.428571428561966
187. 18.428571428563291
188. 18.428571428564432
189. 18.428571428565412
190. 18.428571428566254
191. 18.428571428566979
192. 18.428571428567601
193. 18.428571428568137
194. 18.428571428568599
195. 18.428571428568993
196. 18.428571428569335
197. 18.428571428569626
198. 18.428571428569878
199. 18.428571428570095
200. 18.428571428570280
201. 18.428571428570439
202. 18.428571428570578
203. 18.428571428570695
204. 18.428571428570798
205. 18.428571428570887
206. 18.428571428570962
207. 18.428571428571026
208. 18.428571428571082
209. 18.428571428571132
210. 18.428571428571175
211. 18.428571428571210
212. 18.428571428571242
213. 18.428571428571267
214. 18.428571428571288
215. 18.428571428571306
216. 18.428571428571324
217. 18.428571428571338
218. 18.428571428571349
219. 18.428571428571360
220. 18.428571428571370
221. 18.428571428571377
222. 18.428571428571384
223. 18.428571428571392
224. 18.428571428571395
225. 18.428571428571399
226. 18.428571428571402
227. 18.428571428571406
228. 18.428571428571409
229. 18.428571428571413
230. 18.428571428571416

	Took 231 iterations.
    

F#

// Shape-Machine. Nigel Galloway: July 22nd., 2024
let r=System.Random()
let n=Seq.unfold(fun x->Some(x,(x+3.0)*0.86))(r.NextDouble()* -100.0)|>Seq.pairwise|>Seq.takeWhile(fun(n,g)->n<>g)
printfn "starting with %.50f produces %.50f after %d iterations" (fst(Seq.head n)) (fst(Seq.last n)) (Seq.length n)
Output:
starting with -72.87210186675565637415274977684020996093750000000000 produces 18.42857142857141283798227959778159856796264648437500 after 242 iterations

Java

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Scanner;

public final class ShapeMachine {

	public static void main(String[] args) {
		Scanner reader = new Scanner(System.in);
        System.out.print("Enter a number: ");
        final BigDecimal userChoice = reader.nextBigDecimal();
        System.out.print("Enter a number of decimal places: ");
        final int decimalPlaces = reader.nextInt();
        reader.close();
		
		final BigDecimal epsilon = BigDecimal.TEN.pow(-decimalPlaces - 1, MathContext.DECIMAL128);
		int iterations = 0;
		BigDecimal previous = BigDecimal.ZERO;
		BigDecimal current = userChoice;

		while ( current.subtract(previous).abs().compareTo(epsilon) > 0 ) {
			previous = current;
			current = current.add(THREE).multiply(ZERO86);
			iterations += 1;
		}

		final BigDecimal result = current.setScale(decimalPlaces, RoundingMode.HALF_UP);
		System.out.println(userChoice + " converged to " + result + " after " + iterations + " iterations.");
	}
	
	private static final BigDecimal THREE = new BigDecimal("3.0");
	private static final BigDecimal ZERO86 = new BigDecimal("0.86");

}
Output:
Enter a number: -72
Enter a number of decimal places: 30
-72 converged to 18.428571428571428571428571428571 after 492 iterations.

jq

Works with jq, the C implementation of jq

Works with gojq, the Go implementation of jq

Works with jaq, the Rust implementation of jq

In accordance with the basic task description, here is a solution that does not terminate:

input | recurse(. + 3 | . * 0.86)

To examine the first five generated items, we could use the shell's `head` utility, e.g. as follows:

$ jq -n ' input | recurse(. + 3 | . * 0.86)' <<< 0 | head -n 5
0
2.58
4.7988
6.706968
8.34799248

Notice that the output of `recurse` includes the input value.

To limit the generator programmatically, one could use the `limit/2` built-in:

$ jq -n --argjson n 5 'input | limit($n; recurse(. + 3 | . * 0.86))' <<< 1
1
3.44
5.538399999999999
7.343023999999999
8.89500064

One way to suppress the first item produced by the generator would be to use `whilst/1`:

# like while/2 but emit the final term rather than the first one
def whilst(cond; update):
     def _whilst:
         if cond then update | (., _whilst) else empty end;
     _whilst;

input | whilst(true; . + 3 | .  * 0.86)

To stop when the generated number satisfies `trunc == 18`, one could use the following filter:

whilst(trunc != 18; . + 3 | .  * 0.86)

To determine how many iterations it takes until the truncated value is 18, one could use `until/2`:

$ jq -n '{i:input} | until(.i|trunc == 18; .i += 3 | .i *= 0.86 | .n+=1)' <<< 0
{
  "i": 18.003997862641942,
  "n": 25
}

To determine how many iterations it takes until quiescence:

{a: input}
| until(.aprime == .a;
  .i += 1
  | .aprime=.a
  | .a += 3 | .a  *= 0.86)

Using an initial value of 0, jq produces the result:

{"a":18.428571428571416,"i":233,"aprime":18.428571428571416}

Julia

using Printf
using Plots

function converge(startvalue, decimals = 36, maxiters = 10000)
    current, previous = startvalue, startvalue + 5
    for i in 0:maxiters
        if abs(previous - current) <= big"10.0"^(-decimals)
            return current, i
        end
        previous = current
        current += 3
        current *= big"0.86"
    end
    error("Too many iterations, over $maxiters")
end

print("Enter starting value --> ")
input = something(tryparse(BigFloat, readline()), big"0.0")
print("Enter number of decimal places --> ")
decimals = something(tryparse(Int, readline()), 36)
endvalue, iters = converge(input, decimals)
@printf("%f --> %.*f to %d places after %d repetitions",
   input, decimals, endvalue, decimals, iters)

startvalues = collect(0:0.1:36)
iterationcounts = [last(converge(BigFloat(x))) for x in startvalues]

plot(startvalues, iterationcounts, xlabel = "Starting input", 
   ylabel = "Iterations to reach 36 digit precision")
Output:
Enter starting value --> 4
Enter number of decimal places --> 36
4.000000 --> 18.428571428571428571428571428571428566 to 36 places after 556 repetitions


M2000 Interpreter

An OOP example. Tests for different type of variable. Decimal point is "," for Greeks (by default the decimal point is the systme one, we can use GREEK or LATIN or LOCALE 1032 or any other language ID). For code always decimal point is ".".

superclass MainTest {
unique: 
	document Doc$
	module PutValue {
		.Doc$<=letter$+{
		}	
	}
public:
	property counter{value}=0
	function result {
		for superclass {
			=.Doc$
		}
	}	
	module Test1 (thisType, ThisValue) {
		select case thistype
		case 0
			single a
		case 1
			double a
		case 3
			currency a
		case else
			decimal a
		end select
		a=ThisValue
		aa=a
		.[counter]++
		long long i=1
		do
			o=a
			a+=3  ' double literal value
			a*=.86 ' double literal value
			if o=a then exit
			i++
		always
		for superclass {
			.PutValue format$("{0:8} {1:2:-12} {2::-3} {3}",type$(aa), aa, i, a)
		}
	}
}
document result$
dim a(0 to 3)=MainTest
for i=0 to 3
	a(i).test1 i, 4
	a(i).test1 i, 123456789	
	result$ = "test on a("+i+") so far:"+a(i).counter+{
	}
next
result$ = "Results" + {
}+a(1).result()

clipboard result$
Print #-2, result$
Output:
test on a(0) so far:2
test on a(0) so far:2
test on a(1) so far:2
test on a(2) so far:2
test on a(3) so far:2
Results
Single           4.00  97 18.42857
Single        1.23E+8 203 18.42858
Double           4.00 231 18.4285714285714
Double   123456789.00 336 18.4285714285714
Decimal          4.00 423 18.428571428571428571428571426
Decimal  123456789.00 528 18.428571428571428571428571432
Currency         4.00  72 18.4283
Currency 123456789.00 176 18.4289

Oberon-07

Translation of: ALGOL 68
MODULE ShapeMachine;
IMPORT In, Out;

VAR a, prevA : REAL;
    n, count : INTEGER;

BEGIN
    count := 0;
    In.Int( n );
    a     := FLT( n );
    prevA := 0.0;
    WHILE prevA # a
    DO
        INC(count);
        prevA := a;
        a     := ( a + 3.0 ) * 0.86;
        Out.Real( a, 9 );Out.Ln
    END;
    Out.Int( count, 0 );Out.String( " repetitions" )
END ShapeMachine.
Output:

With 4 as the input value, using Oberonc (Oberon-07 compiler for the JVM) where REAL is 32-bit:

 6.020000
 7.757201
 9.251192
10.536025
11.640982
...
18.428562
18.428564
18.428566
18.428568
18.428568
97 repetitions

With 4 as the input value, using OBNC where REAL is 64-bit:

6.020000E+00
7.757200E+00
9.251192E+00
1.053603E+01
...
1.842857E+01
1.842857E+01
1.842857E+01
231 repetitions

Pascal

Free Pascal

Take care on windows
"and the extended type is available on all Intel x86 processors, except on the Windows 64-bit platform"
Here I have used Win11.

program ShapeMachine;
const
  offset = 3.0;
  factor = 0.86;
var
  before, after: extended;
  iterationsCount: uint32;
begin
  //x = (x+offset)*factor
  //x/factor-x = offset
  //x := offset/(1/factor-1) -> factor must be smaller than 1
  after := 4;
//  after := offset/(1/factor-1);
  iterationsCount := 0;
  Writeln('Start with value ',after);
  repeat
    before := after;
    after := (before + offset) * factor;
    Inc(iterationsCount);
  until before = after;
  writeln(before: 0: 20, ' after ', iterationsCount, ' iterations');
  {$IFDEF WINDOWS}
  readln;
  {$ENDIF}
end.
Output:
on Windows
Start with value  4.0000000000000000E+000
18.42857142857141600000 after 231 iterations

on Linux
Start with value  4.00000000000000000000E+0000
18.42857142857142856850 after 281 iterations

Start with value  1.8428571428571420E+001
18.42857142857142000000 after 1 iterations

PascalABC.NET

begin
  var count := 0;
  var n := ReadInteger;
  var next: real := n;
  var prev: real;
  repeat
    Writeln(next);
    prev := next;
    next := (prev + 3) * 0.86;
    count += 1;
  until prev = next;
  Writeln(count);
end.
Output:
4
4
6.02
7.7572
9.251192
10.53602512
11.6409816032
12.591244178752
13.4084699937267
14.111284194605
14.7157044073603
15.2355057903298
15.6825349796837
16.0669800825279
16.397602870974
16.6819384690377
16.9264670833724
17.1367616917003
17.3176150548622
17.4731489471815
17.6069080945761
17.7219409613354
17.8208692267485
17.9059475350037
...
18.4285714285714
18.4285714285714
18.4285714285714
18.4285714285714
18.4285714285714
18.4285714285714
231

Phix

with javascript_semantics
--atom n = prompt_number("") -- (not js compatible)
atom n = 4
integer count = 0
do
    printf(1,"%.20f\n",n)
    atom prev = n
    n = (n + 3) * 0.86
    count += 1
until n==prev
printf(1,"Took %d iterations.\n",count)
Output:

64-bit (which uses 80-bit floats)

4.00000000000000000000
6.01999999999999999998
7.75720000000000000067
9.25119200000000000035
...
18.42857142857142856499
18.42857142857142856672
18.42857142857142856845
Took 281 iterations.

32-bit (which uses 64-bit floats, as does JavaScript output from p2js)

4.0000000000000000
6.0199999999999996
7.7571999999999992
9.2511919999999996
...
18.4285714285714093
18.4285714285714128
18.4285714285714164
Took 231 iterations.

Python

 a=int(input())
 while True:
     a=(a+3)*0.86
     print(a)

Quackery

  [ $ "bigrat.qky" loadfile ] now!

  [ stack ]                              is places ( --> s )

  [ $ "Starting value: " input
    $->v drop
    $ "Number of decimal places: " input
    $->n drop places put
    0 temp put
    [ 1 temp tally
      2dup
      3 1 v+ 86 100 v*
      2swap 2over places share approx=
      until ]
    places share point$ echo$
    say " to "
    places take echo
    say " places after "
    temp take echo
    say " iterations." cr ]              is task   ( -->   )
Output:
Starting value: 4
Number of decimal places: 36
18.428571428571428571428571428571428566 to 36 places after 556 iterations.

However…

If, rather than specifying a precision to a number of decimal places, we apply mediant rounding to the rational representation that Quackery uses, after each iteration, with an appropriate maximum value for the denominator, it quickly homes in on the limit of the computation i.e. eighteen and three sevenths.

  [ stack ]                               is maxval ( --> s )

  [ $ "Starting value: " input
    $->v drop
    $ "Max denominator: " input
    $->n drop maxval put
    0 temp put
    [ 1 temp tally
      2dup
      3 1 v+ 86 100 v*
      proper maxval share round improper
      2swap 2over v- v0= until ]
    maxval release
    proper$ echo$
    say " after " temp take echo
    say " iterations." cr ]               is task   ( -->   )
Output:
Starting value: 4
Max denominator: 50
18 3/7 after 56 iterations.

Raku

my $input = (+prompt()).FatRat;
my $previous = 0.FatRat;
my $count;
my $places = 36;
loop {
    $input += 3;
    $input ×= .86;
    last if $previous.substr(0,$places) eq $input.substr(0,$places);
    ++$count;
    say ($previous = $input).substr(0,$places);
}
say "$count repetitions";
Output with a 4 fed in at the prompt:
4
6.02
7.7572
9.251192
10.53602512
11.6409816032
12.591244178752
13.40846999372672
14.1112841946049792
14.715704407360282112
15.23550579032984261632
15.6825349796836646500352
16.066980082527951599030272

...
many, many lines omitted
...

18.428571428571428571428571428571416
18.428571428571428571428571428571418
18.428571428571428571428571428571419
18.428571428571428571428571428571420
18.428571428571428571428571428571421
18.428571428571428571428571428571422
18.428571428571428571428571428571423
18.428571428571428571428571428571424
512 repetitions

In the latest iteration of the task instructions, we are to optionally "halt the loop when quiescence has been achieved, i.e. when the value does not change". Unless a precision is specified, "quiescence" will never be achieved. This operation adds more places of precision with every iteration, and will never "quiesce". (Unless run on a processor or with a language that is unable to handle high precision.)

For instance, the 1000th iteration, starting with 4 is exactly equal to:

say (4.FatRat, (* + 3) × .86 … *)[999]
Output:
18.428571428571428571428571428571428571428571428571428571428571428518562611055257476711345657046077536086307719590805662205008932637290716748623508143778473712167435511145273975385354947408188479662139937380449451942842937179508680530588633892945763008511616379084707917069957275072200539351914273993965066030011194811876547904839025263224744832595386782011862097471389181893672211696726485532183264057134602403929706908123592993235863786859888156665186026179826816128847575831458378844885123366878611593252686593421606487555134444315938261367778063531536534964127098858136548553001526656285822374662510184388742700972850063038414950295895060044238800011827580857336812976758443609296077801146559738910594736606435132635929690920618270821813108173656217015589361779205162675360527035288967300528197729261443766412283716792164777168702168039406788952779919915570541752416260293860518467707548712088056167502132216420672641269104901942501949966581723902330182247134406759443834453985391637796764689461663270662662993088449741102622767088092813554110022083926515230853581817905105492221230813528825959115645642043759816744064849863722778041272156387348996418369338438534662612609987037043047038131221189442288876209762806085696386445408093086328602555139121446610496274119187899056474561873403444794760343168250250584159942711177776533259811971409762989699214055857046134462937025863660124732727323402691866232023863821613479844954718192492032583994808226027774091320595373377362720291094591511865887665392365641680216202349251077081257991823441611723818589067580880018475492672710607080810164651535155593521646027992098574736200877274039486002214250862949227962977243520217727369412523884625435318388719886

(Notice that that, while very precise, is only accurate to 64 decimal places.)

RPL

Iterative approach

Works with: RPL version HP-49C
« 0 
  DO OVER 3. + .86 * 
     SWAP 1 +
  UNTIL ROT PICK3 == END
  "count" →TAG
» 'TASK' STO 
4 TASK
Output:
2: 18.4285714283
1: count:163

Direct approach

'X=(X+3)*86/100' SOLVEVX
Output:
1: X=129/7

Rust

fn converge(start_value: f64) -> (f64, i32) {
    let mut current = start_value;
    let mut previous = start_value + 5.0;
    let mut i: i32 = 0;
    loop {
        if (previous - current).abs() <= f64::EPSILON {
            return (current, i);
        }
        previous = current;
        current += 3.0;
        current *= 0.86;
        i += 1;
    }
}

fn main() {
    let start_value = 4.0;
    let (end_value, iterations) = converge(start_value);
    println!(
        "\n{} --> {} to epsilon of {} after {} repetitions\n",
        start_value,
        end_value,
        f64::EPSILON,
        iterations
    );
}
Output:

4 --> 18.428571428571416 to epsilon of 0.0000000000000002220446049250313 after 231 repetitions

V (Vlang)

import os

fn main() {
	mut prev, mut next := f64(0), f64(0)
	mut count := 1
	for prev < 1 {
       prev = os.input_opt("Enter a number: ") or {panic(err)}.f64()
    }
	for {
		println("${next}")
		next = (prev + 3) * 0.86
		if prev == next {break}
		prev = next
		count++
	}
	print("Took ${count} iterations.")
}
Output:
Enter a number: 4
0.0
6.02
7.757199999999999
9.251192
10.53602512
11.6409816032
12.591244178752
13.408469993726719
14.111284194604979
14.71570440736028
...
18.428571428571384
18.42857142857139
18.428571428571395
18.4285714285714
18.428571428571402
18.428571428571406
18.42857142857141
18.428571428571413
18.428571428571416
Took 231 iterations.

Wren

Library: Wren-ioutil

This repeats until the next number (a 64 bit float) equals the previous number which will usually be sometime later than their string/display values (normally limited to 14 digits in Wren CLI) are equal.

import "./ioutil" for Input

var prev = Input.number("")
var count = 1
while (true) {
    var next = (prev + 3) * 0.86
    if (prev == next) break
    System.print(prev = next)
    count = count + 1
}
System.print("Took %(count) iterations.")
Output:

Sample input/output (abridged):

4
6.02
7.7572
9.251192
10.53602512
11.6409816032
12.591244178752
13.408469993727
14.111284194605
14.71570440736
...
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
18.428571428571
Took 231 iterations.

XPL0

Translation of: Python
real A;
[A:= RlIn(0);
while true do
    [A:= A+3.;
    A:= A*0.86;
    RlOut(0, A);
    ];
]
Output:
123
108.36000 95.76960 84.94186 75.63000 67.62180 60.73475 54.81188 49.71822
45.33767 41.57039 38.33054 35.54426 33.14807 31.08734 29.31511 27.79099
26.48026 25.35302 24.38360 23.54989 22.83291 22.21630 21.68602 21.22998
20.83778 20.50049 20.21042 19.96096 19.74643 19.56193 19.40326 19.26680
19.14945 19.04853 18.96173 18.88709 18.82290 18.76769 18.72022 18.67939
18.64427 18.61407 18.58810 18.56577 18.54656 18.53004 18.51584 18.50362
18.49311 18.48408 18.47631 18.46962 18.46388 18.45893 18.45468 18.45103
18.44788 18.44518 18.44285 18.44085 18.43914 18.43766 18.43638 18.43529
18.43435 18.43354 18.43285 18.43225 18.43173 18.43129 18.43091 18.43058
18.43030 18.43006 18.42985 18.42967 18.42952 18.42938 18.42927 18.42917
18.42909 18.42902 18.42895 18.42890 18.42885 18.42881 18.42878 18.42875
18.42873 18.42870 18.42869 18.42867 18.42866 18.42864 18.42863 18.42863
18.42862 18.42861 18.42861 18.42860 18.42860 18.42859 18.42859 18.42859
18.42859 18.42858 18.42858 18.42858 18.42858 18.42858 18.42858 18.42858
18.42858 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857
18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857
18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857 18.42857
Cookies help us deliver our services. By using our services, you agree to our use of cookies.