C言語で医療費控除額を計算する

コード

医療費控除の額がよくわからなかったので、C言語でコードを書いて試してみた。

GitHub にもある。

#include <stdio.h>
#include <math.h>
#include <assert.h>

static int get_medical_expenses_deduction(int payed, int insurance, int income);

int main(int argc, const char * argv[]) {
  // テスト
  assert(get_medical_expenses_deduction(200000, 0, 3000000) == 100000);
  assert(get_medical_expenses_deduction(200000, 50000, 3000000) == 50000);
  assert(get_medical_expenses_deduction(1000000, 0, 3000000) == 900000);
  assert(get_medical_expenses_deduction(1000000, 0, 1000000) == 950000);
  assert(get_medical_expenses_deduction(1000000, 0, 0) == 1000000);

  return 0;
}


/**
 * 医療費控除額を得る
 *
 * @param payed その年に支払った医療費
 * @param insurance 保険金などで補填される金額(生命保険など)
 * @param income その年に得た総所得
 *
 * @return 医療費控除額
 */
static int get_medical_expenses_deduction(int payed, int insurance, int income) {
  static const double income_coe = 0.05;    // 総所得にかける係数
  static const int income_border = 2000000; // 総所得の閾値
  static const int default_val2 = 100000;   // 控除から引くデフォルトの値
  static const int deduction_max = 2000000; // 控除の最高額
  
  
  // 基本となる控除額を算出する
  int val = payed - insurance;
  if(val < 0) {
    val = 0;
  }
  
  
  // 控除から引く額を算出する
  int val2 = default_val2;
  if(income < income_border) {
    // 総所得が閾値未満
    // -> 総所得に係数をかけた額を使用する
    val2 = ceil(income * income_coe);
  }
  
  
  // 控除額を計算する
  int deduction = val - val2;
  if(deduction > deduction_max) {
    deduction = deduction_max;
  }
  if(deduction < 0) {
    deduction = 0;
  }
  
  return deduction;
}

参照

InterfaceBuilder を使用せずにコード内で UIButton のアクションをバインドする

ある UIButton に対して TouchUpInside のイベントにアクションをバインドしたいとき、インターフェースビルダーを使わずに、コードで実現すると下のようになる。

@IBOutlet weak var button: UIButton!

class ViewController: UIViewController {

  override func viewDidLoad() {
    button.addTarget(self,
                     action: #selector(buttonAction(sender:)),
                     for: .touchUpInside)
  }

  @objc func buttonAction(sender: UIButton) {
    // アクションを書く!
  }
}

Mac の性能がよくなく、インターフェースビルダーの動きが緩慢な場合は、インターフェースビルダーの使用は最低限アウトレットだけのバインドだけに留めて、アクションなどはコードで設定すると、作業がはかどる。

UnsafeMutablePointer のパターンをいろいろテストする

はじめに

  • UnsafeMutablePointer の allocate/deallocate/initialize/move などのメソッドを一通り使用する。
  • また、ポインタの扱いでメモリリークが発生しないようにする。

テストしたコードは GitHub にある。

テストで共通使用する関数・クラス

このコードをベースに色々なパターンをテストする。

import Foundation
import CoreAudio

// オブジェクトのアドレスを保存するマップ
var addressMap = [String: Bool]()

// オブジェクトのアドレス(文字列)を得る
func address(_ object: AnyObject) -> String {
  return "\(Unmanaged.passUnretained(object).toOpaque())"
}

// テストの終了処理
func testFinally() {
  assert(addressMap.count == 0)  // アドレスマップの要素数を確認する(0でなければメモリリークをしている
  print("- OK\n")
}


// モッククラス
class Mock {
  
  // インスタンス生成時にアドレス表示&アドレスをマップに保存する
  init () {
    print("init   : \(address(self))")
    addressMap[address(self)] = true  // Store address.
  }
  
  init(_ value: Int) {
    print("init   : \(address(self))")
    addressMap[address(self)] = true  //  Store address.
    
    v1 = value
  }
  
  // deinit() でアドレスマップからアドレスを削除する
  deinit {
    print("deinit : \(address(self))")
    addressMap.removeValue(forKey: address(self))  //  Remove address.
  }
  
  
  // 自由に設定できる変数
  var v1 = Int(0)
}

テストケース

allocate / deallocate パターン

func testAllocateAndDeallocate() {
  print("# \(#function)")
  
  do {
    let p = UnsafeMutablePointer<Mock>.allocate(capacity: 1)
    
    // 未初期化のメモリはアクセスする前に、初期化する必要がある
    // initialize せずに以下のコードを実行するとエラーになる
    //
    // p.pointee.v1 = ...
    
    p.deallocate()  // deallocate をコールしないとメモリリークが発生する
  }
  
  testFinally() // メモリリークが発生していないことを確認する
}

initialize / deinitialize パターン

func testInitializeAndDeinitialize() {
  print("# \(#function)")
  
  do {
    // モックインスタンスを作成する
    var mock = Mock()
    mock.v1 = 10
    
    let p = UnsafeMutablePointer<Mock>.allocate(capacity: 1)
    defer {
      p.deallocate()
    }

    // インスタンスから UnsafeMutablePointer を initialize する    
    p.initialize(from: &mock, count: 1)
    p.pointee.v1 = 20  // initialize した UnsafeMutablePoitner はアクセス可能になる
    
    assert(address(mock) == address(p.pointee)) // インスタンスと UnsafeMutablePointer は同一アドレスである
    assert(mock.v1 == 20)
    
    p.deinitialize(count: 1)  // initialize した分、 deinitialize をコールしないとメモリリークが発生する
  }
  
  testFinally()
}

initialize / move パターン

func testInitializeAndMove() {
  print("# \(#function)")
  
  do {
    // UnsafeMutablePointer を allocate する
    let p = UnsafeMutablePointer<Mock>.allocate(capacity: 1)
    defer {
      p.deallocate()
    }
    
    // インスタンス値から UnsafeMutablePointer を初期化する
    p.initialize(to: Mock())
    p.pointee.v1 = 10
    
    // p を move してインスタンスを取得する
    // move したことにより、 deinitialize しなくても p は deinit される
    let mock = p.move()
    
    // p.deinitialize() は不要

    assert(address(mock) == address(p.pointee))
    assert(mock.v1 == 10)
  }
  
  testFinally()
}

moveInitialize パターン

func testMoveInitialize() {
  print("# \(#function)")
  
  do {
    var mock = Mock()
    mock.v1 = 10
    
    let p = UnsafeMutablePointer<Mock>.allocate(capacity: 1)
    defer {
      p.deallocate()
    }
    
    p.moveInitialize(from: &mock, count: 1)
    p.pointee.v1 = 20
    
    // moveInitialize() したので p.deinitialize() は不要

    assert(address(mock) == address(p.pointee))  // Check same address.
    assert(p.pointee.v1 == 20)
  }
  
  testFinally()
}

initialize/ assign パターン

func testInitializeAndAssign() {
  print("# \(#function)")
  
  do {
    var mock = Mock()
    mock.v1 = 10
    
    var mock2 = Mock()
    mock2.v1 = 20
    
    let p = UnsafeMutablePointer<Mock>.allocate(capacity: 1)
    defer {
      p.deallocate()
    }
    
    p.initialize(from: &mock, count: 1) // mock1 で初期化する
    p.assign(from: &mock2, count: 1) // mock2 をアサインする
    p.pointee.v1 = 30
    
    // UnsafeMutablePointer は mock2 を指している
    assert(address(mock2) == address(p.pointee))  // Check same address.
    assert(mock2.v1 == 30)
    
    p.deinitialize(count: 1)
  }
  
  testFinally()
}

moveAssign パターン

func testMoveAssign() {
  print("# \(#function)")
  
  do {
    var mock = Mock()
    mock.v1 = 10
    
    var mock2 = Mock()
    mock2.v1 = 20
    
    let p = UnsafeMutablePointer<Mock>.allocate(capacity: 1)
    defer {
      p.deallocate()
    }
    
    p.initialize(from: &mock, count: 1) // mock1 で初期化する
    p.moveAssign(from: &mock2, count: 1) // mock2 を move する
    p.pointee.v1 = 30
    
    // UnsafeMutablePointer は mock2 を指している
    assert(address(mock2) == address(p.pointee))  // Check same address.
    assert(mock2.v1 == 30)

    // move したので p.deinitialize() は不要
  }
  
  testFinally()
}

Array パターン

func testArray() {
  print("# \(#function)")
  
  do {
    var array: [Mock] = [Mock(10), Mock(20), Mock(30)]
    
    let p = UnsafeMutablePointer<[Mock]>.allocate(capacity: 1)
    defer {
      p.deallocate()
    }
    
    // Array から UnsafeMutablePointer を初期化する
    p.moveInitialize(from: &array, count: 1)
    p.pointee[0] = Mock(40)
    p.pointee[1] = Mock(50)
    p.pointee[2] = Mock(60)
    
    assert(array.count == p.pointee.count)
    assert(address(array as AnyObject) == address(p.pointee as AnyObject))
    assert(array[0].v1 == 40)
    assert(array[1].v1 == 50)
    assert(array[2].v1 == 60)
  }
  
  testFinally()
}

AudioBufferList パターン

func testAudioBufferList() {
  print("# \(#function)")
  
  do {
    let abl = AudioBufferList.allocate(maximumBuffers: 1)
    free(abl.unsafeMutablePointer) // AudioBufferList を allocate() したあとは free() が必要
  }
}

各テストケースを実行する

上記のテストをまとめて繰り返し実行し、エラーとメモリリークがないことを確認する

while true {
  autoreleasepool {
    testAllocateAndDeallocate()
    testInitializeAndDeinitialize()
    testInitializeAndMove()
    testMoveInitialize()
    testInitializeAndAssign()
    testMoveAssign()
    testArray()
    testAudioBufferList()
    
    Thread.sleep(forTimeInterval: 1)
  }
}

おわり

Swift で数値から日本語形式の文字列を得る (例)1,234 -> 千二百三十四

はじめに

Swift でこんな感じのことをしたく

var v = Int(0)
print(v) // "〇"

v = Int(1)
print(v) // "一"

v = Int(2)
print(v) // "二"

v = Int(1234)
print(v) // "千二百三十四"

v = Int(665061443960367)
print(v) // "六百六十五兆六百十四億四千三百九十六万三百六十七"

フレームワークを作ってみた

JapaneseNumber

このフレームワークを使用するとこんな風にできる

import JapaneseNumber

print("0.japaneseNumber -> \"\(0.japaneseNumber)\"")
// 0.japaneseNumber -> "〇"

print("1.japaneseNumber -> \"\(1.japaneseNumber)\"")
// 1.japaneseNumber -> "一"

print("2.japaneseNumber -> \"\(2.japaneseNumber)\"")
// 2.japaneseNumber -> "二"

print("3.japaneseNumber -> \"\(3.japaneseNumber)\"")
// 3.japaneseNumber -> "三"

print("4.japaneseNumber -> \"\(4.japaneseNumber)\"")
// 4.japaneseNumber -> "四"

print("5.japaneseNumber -> \"\(5.japaneseNumber)\"")
// 5.japaneseNumber -> "五"

print("6.japaneseNumber -> \"\(6.japaneseNumber)\"")
// 6.japaneseNumber -> "六"

print("7.japaneseNumber -> \"\(7.japaneseNumber)\"")
// 7.japaneseNumber -> "七"

print("8.japaneseNumber -> \"\(8.japaneseNumber)\"")
// 8.japaneseNumber -> "八"

print("9.japaneseNumber -> \"\(9.japaneseNumber)\"")
// 9.japaneseNumber -> "九"

print("10.japaneseNumber -> \"\(10.japaneseNumber)\"")
// 10.japaneseNumber -> "十"

print("-1.japaneseNumber -> \"\(Int(-1).japaneseNumber)\"")
// -1.japaneseNumber -> "一"

print("5035.japaneseNumber -> \"\(5035.japaneseNumber)\"")
// 5035.japaneseNumber -> "五千三十五"

print("21038250.japaneseNumber -> \"\(21038250.japaneseNumber)\"")
// 21038250.japaneseNumber -> "二千百三万八千二百五十"

print("325568057586.japaneseNumber -> \"\(325568057586.japaneseNumber)\"")
// 325568057586.japaneseNumber -> "三千二百五十五億六千八百五万七千五百八十六"

print("665061443960367.japaneseNumber -> \"\(665061443960367.japaneseNumber)\"")
// 665061443960367.japaneseNumber -> "六百六十五兆六百十四億四千三百九十六万三百六十七"

print("10937969797677893734.japaneseNumber -> \"\(UInt(10937969797677893734).japaneseNumber)\"")
// 10937969797677893734.japaneseNumber -> "千九十三京七千九百六十九兆七千九百七十六億七千七百八十九万三千七百三十四"

最後に

UInt64(最大値が 18446744073709551615 = 千八百四十四京六千七百四十四兆七百三十七億九百五十五万千六百十五)では

  • 恒河沙(ごうがしゃ)... 1052
  • 那由他(なゆた)... 1060
  • 不可思議(ふかしぎ)... 1064

などの2文字以上の単位の出番がなかった。

おわり

テストケースで UIButton をタップする

import XCTest

class UITests: XCTestCase {

  override func setUp() {
    // Put setup code here. This method is called before the invocation of each test method in the class.

    // In UI tests it is usually best to stop immediately when a failure occurs.
    continueAfterFailure = false

    // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
    XCUIApplication().launch()

    // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
  }

  override func tearDown() {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
  }

  func testOne() {
    let app = XCUIApplication()

    // ボタンのテキストをキーにして、ボタンを得る
    let button = app.buttons["Message"]

    // ボタンの有無をアサートチェックする
    XCTAssertTrue(button.exists)

    // ボタンをタップ
    button.tap()
}

テストケースで UIAlertController のボタンをタップする

import XCTest

class UITests: XCTestCase {
  
  override func setUp() {
    // Put setup code here. This method is called before the invocation of each test method in the class.
    
    // In UI tests it is usually best to stop immediately when a failure occurs.
    continueAfterFailure = false
    
    // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
    XCUIApplication().launch()
    
    // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
  }
  
  override func tearDown() {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
  }
  
  func testOne() {
    let app = XCUIApplication()

    // すでに表示されているアラートを得る
    let alert = app.alerts.element

    // アラートのテキストをアサートチェックする
    XCTAssertTrue(alert.staticTexts["Message"].exists)
    
    // アラートのボタンを、テキストをキーにして得る
    let alertButton = alert.buttons["OK"]

    // アラートのボタンの有無をアサートチェックする
    XCTAssertTrue(alertButton.exists)

    // アラートのボタンをタップする
    alertButton.tap()
  }